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 总结