1 相干术语
在理解形象工厂模式之前,首先来理解一下两个术语:
- 产品等级构造
- 产品族
1.1 产品等级构造
产品等级构造也就是产品的继承构造,例如一个抽象类是电视机,子类有不同品牌的电视机,比方海尔电视机,海信电视机,TCL 电视机,而形象电视机与具体品牌的电视机之间形成了一个产品等级构造,形象电视机是父类,而具体品牌的电视机是子类。
1.2 产品族
产品族是指由一个同一个工厂产生的位于不同产品等级构造中的一组产品,例如海尔电器工厂生产的海尔电视机,海尔电冰箱。海尔电视机位于电视机产品等级构造中,海尔电冰箱位于电冰箱产品等级构造中,海尔电视机与海尔电冰箱独特形成了一个产品族。
两者示意图如下:
2 形象工厂模式
** 形象工厂模式:提供一个创立一系列相干或相互依赖对象的接口,而无须指定它们具体的类。
形象工厂模式又叫 Kit 模式,是一种对象创立型模式。**
结构图如下:
形象工厂模式蕴含四个角色:
- AbstractFactory(形象工厂):申明了一组用于创立一族产品的办法,每一个办法对应一种产品
- ConcreteFactory(具体工厂):实现了在形象工厂中申明的创立产品的办法,生成一组具体产品,这些产品形成了一个产品族,每一个产品都位于某个产品的等级构造中
- AbstractProduct(形象产品):为每种产品申明接口,在形象产品中申明了产品所具备的业务办法
- ConcreteProduct(具体产品):定义具体工厂生产的具体对象,实现在形象层产品接口中申明的业务办法
3 实例
界面皮肤库设计:开发一套皮肤库,用户能够通过菜单抉择皮肤,不同的皮肤提供视觉不同的按钮,文本框等 UI 元素。
这里简略起见假如开发两套皮肤:
- 秋季皮肤(SpringSkin)
- 冬季皮肤(SummerSkin)
每套皮肤具备以下 UI 元素:
- 按钮(Button)
- 文本框(TextField)
- 组合框(ComboBox)
首先是 UI 元素,包含形象元素以及具体元素:
interface Button
{void display();
}
class SpringButton implements Button
{public void display()
{System.out.println("秋季皮肤按钮");
}
}
class SummerButton implements Button
{public void display()
{System.out.println("冬季皮肤按钮");
}
}
interface TextField
{void display();
}
class SpringTextField implements TextField
{public void display()
{System.out.println("秋季皮肤文本框");
}
}
class SummerTextField implements TextField
{public void display()
{System.out.println("冬季皮肤文本框");
}
}
interface ComboBox
{void display();
}
class SpringComboBox implements ComboBox
{public void display()
{System.out.println("秋季皮肤组合框");
}
}
class SummerComboBox implements ComboBox
{public void display()
{System.out.println("冬季皮肤组合框");
}
}
接着是工厂类,包含形象工厂以及具体工厂:
interface SkinFactory
{Button createButton();
TextField createTextField();
ComboBox createComboBox();}
class SpringSkinFactory implements SkinFactory
{public Button createButton()
{return new SpringButton();
}
public TextField createTextField()
{return new SpringTextField();
}
public ComboBox createComboBox()
{return new SpringComboBox();
}
}
class SummerSkinFactory implements SkinFactory
{public Button createButton()
{return new SummerButton();
}
public TextField createTextField()
{return new SummerTextField();
}
public ComboBox createComboBox()
{return new SummerComboBox();
}
}
测试:
public class Test
{public static void main(String[] args) {SkinFactory factory = new SpringSkinFactory();
factory.createButton().display();
factory.createTextField().display();
factory.createComboBox().display();
factory = new SummerSkinFactory();
factory.createButton().display();
factory.createTextField().display();
factory.createComboBox().display();
}
}
4 无关 OCP
尽管应用形象工厂模式减少新的皮肤界面十分不便,然而如果减少一个 UI 元素,会批改大量的代码,须要批改形象工厂以及每一个具体工厂类,也就是说,不可能在合乎 OCP(凋谢闭合准则)的前提下减少新的组件。
这是形象工厂模式的最大毛病,只管减少新的产品族(这里是皮肤)十分不便,然而减少新的产品等级构造(这里是 UI 元素)很麻烦。形象工厂模式的这种性质叫做开闭准则的歪斜性。因而设计人员在设计之初须要全面思考,否则新增产品构造会导致大量的代码批改。
5 次要长处
- 隔离:形象工厂模式隔离了具体类的生成,使得客户并不需要晓得什么被创立。因为这种隔离更换一个具体工厂类变得很绝对容易,所有的具体工厂都实现了在形象工厂中申明的那些公共接口,因而只需扭转具体工厂的实例,就能够在某种程度上扭转整个软件系统的行为
- 同一产品族对象:当一个产品族中的多个对象被设计成一起工作时,它可能保障客户端始终只应用同一个产品族中的对象
- 减少产品族容易:减少新的产品族容易,毋庸批改已有零碎,合乎 OCP
6 次要毛病
次要毛病是减少新的产品等级构造麻烦,须要对系统进行大量的批改,违反了 OCP
7 实用场景
- 一个零碎不当应依赖与产品类实例如何被创立,组合和表白细节,这对于所有类型的工厂模式都是很重要的,用户毋庸关怀对象的创立过程,将对象的创立以及应用解耦
- 零碎中有多于一个的产品族,而每次只应用其中某一产品族
- 属于同一个产品族的产品将在一起应用,这一束缚必须在零碎的设计中体现进去。同一个产品族中的产品能够是没有任何关系的对象,然而它们都具备一些独特的束缚。例如同一皮肤下的按钮以及文本框,按钮与文本框没有间接分割,然而都属于同一皮肤
- 产品等级构造稳固,设计实现后,不会向零碎中减少新的产品等级构造或者删除已有的产品等级构造
8 总结