从简单到复杂有简单工厂模式-->工厂方法模式-->抽象工厂模式
简单工厂模式(Simple Factory Pattern)
定义
又称为静态工厂方法(Static Factory Method)模式
,它属于类创建型模式。在简单工厂模式中,可以根据参数
的不同返回不同类的实例。简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
产生背景
当一个模块只需要一个工厂类,没必要把工厂类也抽象出来的时候,使用静态方法就行。就像规模小的时候,各种产品都在一个工厂里混着生产,有点类似小作坊。
UML图
代码
public class SimpleDrinkFactory {
public static <T extends Drink> T getDrink(Class<T> c) {
//定义一个饮料
Drink drink = null;
try {
drink = (Drink) Class.forName(c.getName()).newInstance();
} catch (Exception e) {
System.out.println("生产饮料失败!");
}
return (T) drink;
}
}
public class SimpleDrinkFactoryTest {
@Test
public void test() {
Drink wine = SimpleDrinkFactory.getDrink(Wine.class);
wine.getName();
Drink milk = SimpleDrinkFactory.getDrink(Milk.class);
milk.getName();
Drink juice = SimpleDrinkFactory.getDrink(Juice.class);
juice.getName();
}
}
使用场景:
- 日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。
- 数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。
- 设计一个连接服务器的框架,需要三个协议,"POP3"、"IMAP"、"HTTP",可以把这三个作为产品类,共同实现一个接口。
工厂方法模式(Factory Method Pattern)
意图
定义一个用于创建对象的接口,让子类决定实例化哪一个类。 Factory Method使一个类的实例化延迟到其子类。
适用性
在下列情况下可以使用 Factory Method模式:
- 当一个类不知道它所必须创建的对象的类的时候。
- 当一个类希望由它的子类来指定它所创建的对象的时候。
- 当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。
结构
参与者
- P r o d u c t( D o c u m e n t )
-- 定义工厂方法所创建的对象的接口。 - C o n c r e t e P r o d u c t(M y D o c u m e n t)
-- 实现P r o d u c t接口。 - C r e a t o r(A p p l i c a t i o n)
-- 声明工厂方法,该方法返回一个 P r o d u c t类型的对象。 C r e a t o r也可以定义一个工厂方法的缺省实现,它返回一个缺省的 C o n c r e t e P r o d u c t对象。
-- 可以调用工厂方法以创建一个 P r o d u c t对象。 - C o n c r e t e C r e a t o r(M y A p p l i c a t i o n)
-- 重定义工厂方法以返回一个 C o n c r e t e P r o d u c t实例。
协作
- Creator依赖于它的子类来定义工厂方法,所以它返回一个适当的 C o n c r e t e P r o d u c t实例。
抽象工厂模式(Abstract Factory Pattern)
意图
提供一个创建一系列相关
或相互依赖
对象的接口,而无需指定它们具体的类。重点在于在于一系列
、相关(相互依赖)
两个词。
结 构
适用性
在以下情况可以使用 Abstract Factory模式
- 一个系统要独立于它的产品的创建、组合和表示时。
- 一个系统要由多个产品系列中的一个来配置时。
- 当你要强调一系列相关的产品对象的设计以便进行联合使用时。
- 当你提供一个产品类库,而只想显示它们的接口而不是实现时。
举例
知乎上有个很好的例子,就是远程武器的例子,比如手枪、步枪、打炮、弩。这些武器的生产工厂不止生产武器,同时生产配套的弹药(箭矢),这个注意一个词配套,也就是这些弹药和武器是配套使用的,不能混着来,手枪不能用步枪子弹,步枪也不能用手枪子弹,大炮就更不用说了。而对于客户端来说只需要工厂就行,不需要关系这些武器和这些弹药如何搭配,把搭配组合的事儿让工厂管了。客户端只需要给抽象工厂引用替换具体的工厂实例,就能从工厂中获取到相应的武器和对应的弹药,而不会混乱。
区别
和工厂方法模式的区别在于,工厂方法模式只关心单一产品的生产,而抽象工厂模式关心的是整体配套,工厂方法模式有些类似工厂中的生产线,只关心这条生产线是生产武器还是弹药。