创建性模式有五种:
1.工厂模式
①简单工厂模式(经常被用到,不属于GoF23种设计模式)
②工厂方法模式
③抽象工厂模式
2.建造者模式
3.原型模式
4.单例模式
工厂方法模式
工厂方法(Factory Method)模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。
角色
抽象工厂(Creator)角色:是工厂方法模式的核心,与应用程序无关。任何在模式中创建的对象的工厂类必须实现这个接口。
具体工厂(Concrete Creator)角色:这是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建产品对象。在上图中有两个这样的角色:BulbCreator与TubeCreator。
抽象产品(Product)角色:工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。在上图中,这个角色是Light。
具体产品(Concrete Product)角色:这个角色实现了抽象产品角色所定义的接口。某具体产品有专门的具体工厂创建,它们之间往往一一对应。
优缺点
优点:
1、 在工厂方法中,用户只需要知道所要产品的具体工厂,无须关系具体的创建过程,甚至不需要具体产品类的类名。
2、 在系统增加新的产品时,我们只需要添加一个具体产品类和对应的实现工厂,无需对原工厂进行任何修改,很好地符合了“开闭原则”。
缺点:
1、 每次增加一个产品时,都需要增加一个具体类和对象实现工厂,是的系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。
类图

代码实现
package com.sun.factory;
/**
* 工厂抽象类
* @author work
*
*/
public interface IFactory {
public Operaction createOperaction() ;
}
package com.sun.factory;
/**
* 抽象产品角色
* @author work
*
*/
public abstract class Operaction {
double numberA;
double numberB;
public abstract double getResult();
public double getNumberA() {
return numberA;
}
public void setNumberA(double numberA) {
this.numberA = numberA;
}
public double getNumberB() {
return numberB;
}
public void setNumberB(double numberB) {
this.numberB = numberB;
}
}
package com.sun.factory;
/**
* 具体工厂加法
* @author work
*
*/
public class AddFactory implements IFactory{
@Override
public Operaction createOperaction() {
// TODO Auto-generated method stub
return new AddOperaction();
}
}
package com.sun.factory;
/**
* 具体产品加
* @author work
*
*/
public class AddOperaction extends Operaction{
@Override
public double getResult() {
// TODO Auto-generated method stub
return numberA+numberB;
}
}
package com.sun.factory;
/**
* 具体工厂减法
* @author work
*
*/
public class MultFactory implements IFactory{
@Override
public Operaction createOperaction() {
// TODO Auto-generated method stub
return new MultOperaction();
}
}
package com.sun.factory;
/**
* 具体产品减法
* @author work
*
*/
public class MultOperaction extends Operaction{
@Override
public double getResult() {
// TODO Auto-generated method stub
return numberA*numberB;
}
}
public class OperactionSource {
public static Operaction createOperaction(String oper) {
IFactory factory;
switch (oper) {
case "+":
factory = new AddFactory();
break;
case "-":
factory = new MultFactory();
break;
default:
throw new RuntimeException("不存在");
}
return factory.createOperaction();
}
public static void main(String[] args) {
Operaction operaction = createOperaction("+");
operaction.setNumberA(1);
operaction.setNumberB(2);
System.out.println(operaction.getResult());
}
}
这就是工厂方法模式的典型代码实现。这样当我们新增一种 Operaction的时候,只需要新增一个实现IFactory接口的 Factory 类即可。所以,工厂方法模式比起简单工厂模式更加符合开闭原则。从上面的工厂方法的实现来看起来一切都很完美,但是实际上存在很大问题。问题存在于这些工厂类的使用上,和简单工厂的代码版本非常相似,引入工厂方法非但没有解决问题,反倒让设计变得更加复杂了,我们可以为工厂类再创建一个简单工厂,也就是工厂的工厂,用来创建工厂类对象
public class OperactionMap {
private static Map<String,IFactory> map = new HashMap<>();
static {
map.put("+",new AddFactory());
map.put("-",new MultFactory());
}
public static IFactory getOperactionFactory(String oper) {
if(oper==null || oper.isEmpty()) {
throw new RuntimeException("参数为空");
}
IFactory factory = map.get(oper);
return factory;
}
public static void main(String[] args) {
IFactory operactionFactory = getOperactionFactory("+");
Operaction operaction = operactionFactory.createOperaction();
operaction.setNumberA(11d);
operaction.setNumberB(12d);
System.out.println(operaction.getResult());
}
}
我们只需要创建新的operaction类和operactionFactory 类,将新的operactionFactory 对象添加到 map中即可。代码的改动非常少,基本上符合开闭原则。
简单工厂和工厂方法的使用
当对象的创建逻辑比较复杂,不只是简单的new一下就可以,而是要组合其他类对象,做各种初始化操作的时候,我们推荐使用工厂方法模式,将复杂的创建逻辑拆分到多个工厂类中,让每个工厂类都不至于过于复杂。而使用简单工厂模式,将所有的创建逻辑都放到一个工厂类中,会导致这个工厂类变得很复杂,代码可读性差,维护困难。除此之外,如果工厂要返回多种不同的对象,为了避免大量的switch-case(或者if-else)逻辑判断我们也建议使用工厂方法模式
如果对象的创建逻辑简单则推荐使用简单工厂