行为目的:
创建一个接口(interface),用于创建关联类或者依赖类的类组,而不需指定其具体实现类。
问题起源:
假如我们需要这么一个工具,用于创建不同显示风格的界面,这些不同风格的界面将包含各自特色的按钮,输入框,滚动框等内容。而对于最后向用户展示的界面,将可以通过一键设置。面向对象设计原则之一“面向接口设计”,基于此,有必要创建一个抽象的接口,用于定义关联类或者依赖类的创建,再根据接口去实现具体的类。
使用情况:
1)系统依赖于它所包含的内容是如何创建,组合和展示的;
2)系统是由多个内容类组成的;
3)相关联的类组被设计为同时使用,并需要关注其约束条件的
4)需要提供一个产品类库,只希望显示其接口内容,而不需要让客户程序员知道其实现细节。
UML结构框图:
UML框图说明:
使用说明:
通常情况下具体工厂类都是在运行时创建的。工厂实例通过特别的方式生产其部件产品类,如果要实现不一样风格的工厂实例,需要创建另一个工厂类。抽象工厂接口只负责定义具体工厂类创建部件类的方法。
模式优缺点:
1)使具体工厂类实现解耦。减少不同风格之间产品的耦合性。通过调用抽象工厂类,使客户代码与具体工厂类之间实现解耦。客户代码通过抽象工厂接口实现不同实例,部件类在工厂实例类中也是相互独立的,且不会出现在客户类代码中。
2)客户代码可以非常容易的在工厂类之间切换。工厂实现类其实在每次应用中只出现一次,即实例化时。所以客户代码非常容易在工厂实现类之间进行切换,只需要在实例化接口的部分更换为其他工厂实例类,就可以实现其他工厂实例类所有的配置和效果。
3)保持部件类的一致性。一旦部件类定义为相互之间特定的通讯模式,客户代码就可以非常方便地从工厂实例类中一次性获取到相应的所有内容。
4)添加新的部件类接口方法将变得困难。在抽象工厂方法中添加生成新的部件类方法将非常不容易,当在抽象工厂类中添加新的部件类实现,那么就需要在所有的工厂实现类中实现该方法,否则程序将不会通过编译期(还好是在编译期出现错误)。
实现细节:
1),实现类采用单例模式。对于一个部件组的工厂实例类,通常采用单例模式是最佳方法。
2),抽象工厂类只定义了生成部件类的方法,需要部件类自己去定义如何去创建自身,通常方法是为任何一个部件类创建工厂方法来实现。抽象工厂方法通过覆盖超类方法来实现具体的子类,即使子类只有一点点不同,也需要重新创建该子类。如果工厂子类比较相似度很高的时候,可以通过结合原型方法来实现新的工厂方法子类,先通过原型复制得到相同的子类(对其原型进行缓存),然后再对其不一样的属性进行重新设置。
3),基于抽象工厂模式缺点,添加新的部件类接口方法将变得异常困难,但是这样做是值得的。这就要求我们在设计接口的时候,需要花更多的时间去考虑实现细节。
示例代码:
模式在Java类库中的应用
关联模式:
抽象工厂通常与工厂方法和原型模式配合使用,而且通常具体的工厂实现类都是单例的。