场景

  • new 对象的替代方案
  • 需要灵活、可扩展的框架时
  • 在异构项目中,从外部产生的对象
  • 测试驱动开发框架下使用。测试驱动开发 -TDD

工厂方法模式

定义

定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。

工厂方法模式的通用类图

抽象产品类Product负责定义产品的共性,实现对事物最抽象的定义;
Creator为抽象的创建类,即抽象工厂,具体如何创建产品类是由具体的实现工厂ConcreteCreator完成的。

优点

  • 良好的封装,代码结构清晰,降低模块间的耦合;
  • 良好的扩展性;
  • 屏蔽具体的产品类,只要接口不变,系统中上层模块就不需要发生变化。

高层模块只需要知道产品的抽象类,不关心实现类,符合迪米特法则;
只依赖产品的抽象,符合倒置原则;
使用产品子类替换父类时也没有问题,符合里氏替换原则;

缺点

对于不同类型的产品都要增加不同类型的工厂来管理,增加代码的复杂性

实现

通用实现

产品类:

1
2
3
4
5
6
7
8
9
10
11
12
public abstract class Product{
public abstract void method1();
public void method2(){}
}

public class Product1 extends Product{
public void method1(){}
}

public class Product2 extends Product{
public void method1(){}
}

工厂类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public abstract class Factory{
public abstract <T extends Product> T create(Class<T> c);
}

public class ConcreteFactory extends Factory{

public <T extends Product> T create(Class<T> c){
Product p = null;
try{
p = (Product)Class.forName(c.getName()).newInstance();
}catch(Exception e){

}
return (T)p;
}
}

使用:

1
2
Factory factory = new ConcreteFactory();
Product p = factory.createt(Product1.class);

缩小为简单工厂

去掉抽象的Factory类,create()方法变为静态方法即可。

1
2
3
4
5
6
7
8
9
10
11
12
public void Factory{

public static <T extends Product> T create(Class<T> c){
Product p = null;
try{
p = (Product)Class.forName(c.getName()).newInstance();
}catch(Exception e){

}
return (T)p;
}
}

调用代码:

1
Product p = Factory.create(Product1.class);

升级为多个工厂类

遇到复杂情况下,一个工厂类初始化需要耗费很多资源,这样可以将工厂类细化拆分。

1
2
3
4
5
6
7
8
9
10
11
12
public class Factory1 extends Factory{
public static Product create(){
return new Product1();
}

}

public class Factory2 extends Factory{
public static Product create(){
return new Product2();
}
}

这样的好处是职责清晰,结构简单,但是可扩展性和可维护性差了些。
一般情况下,再增加一个协调类,避免调用者直接与各个子工厂类交流,协调类的作用是封装子工厂类,对高层模块提供统一的访问接口。

替代单例模式

通过反射的方式来创建唯一一个实例

延迟初始化

一个对象被使用完毕后,并不立即释放,工厂类保持其初始状态,等待再次被使用。

延迟加载框架可以被扩展为,限制某个产品类的最大实例化数量(如链接池的最大链接数量)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class ProductFactory{

private static final Map<String,Product> pMap = new HashMap();

public static synchronized Product createProduct(String type) throws Exception{
Product p = null;
if(pMap.containsKey(type)){
p = pMap.get(type);
}else{
if(type.equals("Product1")){
p = new Product1();
}else{
p = new Product2();
}
}
return product;
}
}

定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。

https://www.zhihu.com/question/24843188

https://www.jianshu.com/p/83ef48ce635b

https://blog.csdn.net/buyulian/article/details/79203880

https://blog.csdn.net/qianhaifeng2012/article/details/52014773

https://www.cnblogs.com/aspirant/p/8980573.html

http://www.akathink.com/2016/08/01/%E5%BD%BB%E5%BA%95%E6%90%9E%E6%87%82%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F/