抽象工厂模式
产品等级结构和产品族
工厂方法模式中具体工厂负责生产具体的产品
每一个具体工厂对应一种具体的产品
工厂方法具有唯一性
一般情况下:一个具体工厂中只有一个或一组重载的工厂方法
有时候希望一个一个工厂可以提供多个产品对象
而不是单一的产品对象
产品等级结构:
产品等级结构即产品的继承结构,如一个抽象类是电视机
子类有海尔电视机、海信电视机等
抽象电视机与具体与具体品牌的电视机之间构成了一个产品等级结构
抽象电视机是父类,具体品牌的电视机是其子类
产品族:
在抽象工厂模式中
产品族是指由同一个工厂生产的
位于不同产品等级结构中的一组产品
如海尔电器工厂生产海尔电视、海尔冰箱等
海尔电视机位于电视机产品等级结构中
海尔电冰箱位于电冰箱产品等级结构中
海尔电视机、海尔电冰箱构成了一个产品族
图示:
不同颜色的多个正方形、圆形、椭圆分别构成了三个不同的产品等级结构
相同颜色的正方形、圆形、椭圆形构成了一个产品族
每一个形状对象都位于某个产品族
并属于产品等级结构
图中一共有五个产品族分别属于三个不同的等级结构
只要指明一个产品所处的产品族以及它所属的等级结构,就可以唯一确定这个产品
当系统所提供的工厂生产的具体产品并不是一个简单的对象,而是多个位于不同产品等级结
构、属于不同类型的具体产品时就可以使用抽象工厂模式。
抽象工厂模式是所有形式的工厂模式中最为抽象和最具一般性的一种形式。
抽象工厂模式与工厂方法模式最大的区别在于,
工厂方法模式针对的是一个产品等级结构,而抽象工厂模式需要面对多个产品等级结构,一
个工厂等级结构可以负责多个不同产品等级结构中的产品对象的创建。
当一个工厂等级结构
可以创建出分属于不同产品等级结构的一个产品族中的所有对象时,抽象工厂模式比工厂方
法模式更为简单、更有效率。
抽象工厂模式示意图:
每一个具体工厂可以生产属于一个产品族的所有产品,例如生产颜色相同的正方
形、圆形和椭圆形,所生产的产品又位于不同的产品等级结构中。
相关概述:
抽象工厂模式为创建一组对象提供了一种解决方案
与工厂方法模式相比,抽象工厂模式中的具体工厂不只是创建一种产品
他只负责创建一族产品
定义:
提供了一个创建一系列相关或相互依赖对象的接口
无须知道指定他们具体的类
抽象工厂模式又称为Kit模式,他是一种创建型模式
抽象工厂模式中,每一个具体工厂都提供了多个工厂方法用于产生多种不同类型的产品
这些产品构成了一个产品族
图示:
角色:
AbstractFactory(抽象工厂):它声明了一组用于创建一族产品的方法,每一个方法对应一
种产品。
abstract class AbstractFactory { public abstract AbstractProductA createProductA(); //工厂方法一 public abstract AbstractProductB createProductB(); //工厂方法二 …… }
ConcreteFactory(具体工厂):它实现了在抽象工厂中声明的创建产品的方法,生成一组具
体产品,这些产品构成了一个产品族,每一个产品都位于某个产品等级结构中。
class ConcreteFactory1 extends AbstractFactory { //工厂方法一 public AbstractProductA createProductA() { return new ConcreteProductA1(); } //工厂方法二 public AbstractProductB createProductB() { return new ConcreteProductB1(); } …… }
AbstractProduct(抽象产品):它为每种产品声明接口,在抽象产品中声明了产品所具有的
业务方法。
ConcreteProduct(具体产品):它定义具体工厂生产的具体产品对象,实现抽象产品接口中
声明的业务方法。
事例:
公司欲开发一套界面皮肤库,可以对Java桌面软件进行界面美化。
该皮肤库需要具备良好的灵活性和可扩展性,用户可以自由选择不同的皮肤,开发人员可以
在不修改既有代码的基础上增加新的皮肤。
解决方法:
//抽像产品 //按钮接口 interface Button { public void display(); }
//具体产品 public class SummerButton implements Button { @Override public void display() { System.out.println("浅蓝色按钮"); } }
//具体产品 public class SpringButton implements Button { @Override public void display() { System.out.println("浅绿色按钮"); } }
//抽象产品 public interface TextField { public void display(); }
//具体产品 public class SpringTextField implements TextField { @Override public void display() { System.out.println("显示绿色文本框"); } }
//具体产品 public class SummerTextField implements TextField { @Override public void display() { System.out.println("显示蓝色文本框"); } }
//抽象产品 public interface ComboBox { public void displat(); }
//具体产品 public class SpringComboBox implements ComboBox { @Override public void displat() { System.out.println("显示绿色边框组合"); } }
//具体产品 public class SummerComboBox implements ComboBox { @Override public void displat() { System.out.println("显示蓝色边框组合"); } }
//抽象工厂 public interface SkinFactory { public Button createButton(); public TextField createTextField(); public ComboBox createComboBox(); }
//具体工厂:spring皮肤工厂 public class SpringSkinFactory implements SkinFactory { @Override public Button createButton() { return new SpringButton(); } @Override public TextField createTextField() { return new SpringTextField(); } @Override public ComboBox createComboBox() { return new SpringComboBox(); } }
//具体工厂:summer皮肤工厂 public class SummerSkinFactory implements SkinFactory { @Override public Button createButton() { return new SummerButton(); } @Override public TextField createTextField() { return new SummerTextField(); } @Override public ComboBox createComboBox() { return new SummerComboBox(); } }
测试:
public class client { public static void main(String[] args) { //使用抽象层进行定义 SkinFactory skinFactory; Button button; TextField textField; ComboBox comboBox; skinFactory = new SpringSkinFactory(); button = skinFactory.createButton(); textField = skinFactory.createTextField(); comboBox = skinFactory.createComboBox(); button.display(); textField.display(); comboBox.displat(); } }
此时的图构:
“开闭原则”要求系统对扩展开放,对修改封闭,通过扩展达
到增强其功能的目的,对于涉及到多个产品族与多个产品等级结构的系统,其功能增强包括
两方面:
(1) 增加产品族:对于增加新的产品族,抽象工厂模式很好地支持了“开闭原则”,只需要增加
具体产品并对应增加一个新的具体工厂,对已有代码无须做任何修改。
(2) 增加新的产品等级结构:对于增加新的产品等级结构,需要修改所有的工厂角色,包括抽
象工厂类,在所有的工厂类中都需要增加生产新产品的方法,违背了“开闭原则”。
主要优点:
(1) 抽象工厂模式隔离了具体类的生成,使得客户并不需要知道什么被创建。由于这种隔离,
更换一个具体工厂就变得相对容易,所有的具体工厂都实现了抽象工厂中定义的那些公共接
口,因此只需改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。
(2) 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产
品族中的对象。
(3) 增加新的产品族很方便,无须修改已有系统,符合“开闭原则”。
缺点:
增加新的产品等级结构麻烦,需要对原有系统进行较大的修改,甚至需要修改抽象层代码,
这显然会带来较大的不便,违背了“开闭原则”。
使用场景:
(1) 一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有类型的工
厂模式都是很重要的,用户无须关心对象的创建过程,将对象的创建和使用解耦。
(2) 系统中有多于一个的产品族,而每次只使用其中某一产品族。可以通过配置文件等方式来
使得用户可以动态改变产品族,也可以很方便地增加新的产品族。
(3) 属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来。同一个
产品族中的产品可以是没有任何关系的对象,但是它们都具有一些共同的约束,如同一操作
系统下的按钮和文本框,按钮与文本框之间没有直接关系,但它们都是属于某一操作系统
的,此时具有一个共同的约束条件:操作系统的类型。
(4) 产品等级结构稳定,设计完成之后,不会向系统中增加新的产品等级结构或者删除已有的
产品等级结构。