工厂模式
1. 三种工厂模式说明
1.1 三种工厂模式区分
一句话概括工厂模式
- 简单工厂:一个工厂类,一个产品抽象类(用固定原理产生同理对象)
- 工厂方法:多个工厂类,一个产品抽象类(用不同原理产生同类对象)
- 抽象工厂:多个工厂类,多个产品抽象类(产生不同对象)
生活中的工厂模式
- 简单工厂类:一个麦当劳店,可以生产多种汉堡。
- 工厂方法类:一个麦当劳店,可以生产多种汉堡。一个肯德基店,也可以生产多种汉堡。
- 抽象工厂类:百胜餐饮集团下有肯德基和百事公司,肯德基生产汉堡,百事公司生成百事可乐。
1.2 简单(静态)工厂模式
简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。它通常指创建某一个统一的父类下的某种子类的实例。
简单工厂模式定义了一个创建对象的类,由这来类来封装实例化对象的行为(代码)
在我们要大量的创建某种、某类或者某批对象时,就使用到简单工厂模式
简单工厂要求工厂需要了解所有产品的实现细节,当客户传入参数给工厂时,工厂才能实例化对应的产品对象。这也要求每当有新产品加入时必须要修改工厂类,违反了开闭原则。由此引出工厂模式
1.3 工厂模式
工厂模式中,工厂被抽象出来一个抽象类(或接口),而具体的实例化操作需要由子类实现,相当于子工厂。
这样做可以当产品类的实例化操作延迟到工厂子类中完成。由工厂子类来决定应该实例化哪一个具体实现类。
现在,如果你新增了一个产品,那么你不需要修改原有的工厂,但你需要新增一个新的工厂实现类,来负责对你新产品的生产。这样符合开闭原则。
这个模式在jdk中有多种应用,其中生产迭代器也运用到了工厂的思想:
Collection可以被视为抽象工厂类,LinkedList和ArrayList是其实现类,他们分别负责生产ListItr和Itr两个产品。而Iterator是这两个产品的父类。
1.4 抽象工厂模式
抽象工厂使一个工厂不仅仅只能生产某一个大类的产品,它是多个工厂模式的父类抽象,是工厂模式的扩展。
工厂方法和抽象工厂的概念比较接近,两个模式没有特别大的区别,实际运用应该不用分那么清
从下图可以看出,抽象工厂仅仅只是让工厂可以生产不同类别的产品而已。
同时,这种模式也有简单工厂的毛病:新增一个产品体系的时候,需要对抽象工厂和子类进行修改,违反开闭原则
1.5 静态工厂与抽象工厂
如果工厂只有固定的一个,那么就用静态工厂就行了,因为不需要多种实现,也就不需要使用对象和多态。
如果工厂有多种实现,分别使用了不同的创造对象的原理,那么就不应该使用静态工厂,而应该将工厂视为可替换的对象,使用抽象方法来约束多个工厂的实现的行为。而这个工厂的具体实现的选择应该由使用方给定(外部注入)
2. 应用
使用场景:
- 日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方
- 数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。
- 设计一个连接服务器的框架,需要三个协议,“POP3”、“IMAP”、“HTTP”,可以把这三个作为产品类,共同实现一个接口。
3. 警醒
工厂模式要警惕和类名产生直接关联,最好不用通过class反射获取对象。
工厂模式是用来干什么的?它属于创建模式,是解决子类创建问题的。换句话来说,调用者在调用时,并不知道(并不关心)运行时需要创建的到底是哪一个对象(不知道类名)。如果直接传入一个类名,那为何不直接new一个对象?何必走工厂模式呢。
4. 枚举类工厂
public enum Factory {
CIRCLE(new Circle(),"CIRCLE"),
RECTANGLE(new Rectangle(),"RECTANGLE"),
SQUARE(new Square(),"SQUARE");
// 成员变量,省略set/get
private Shape shape;
private String name;
// 普通方法
public static Shape getShape(String name) {
for (Factory c : Factory.values()) {
if (c.name == name) {
return c.shape;
}
}
return null;
}
// 构造方法
private Factory(Shape shape, String name) {
this.shape = shape;
this.name = name;
}
}
/*使用枚举类*/
Factory.getShape("CIRCLE").draw();
Factory.getShape("RECTANGLE").draw();
Factory.getShape("SQUARE").draw();