首页 > 代码库 > 设计模式学习03—抽象工厂模式

设计模式学习03—抽象工厂模式

1、动机与定义

     工厂模式中,一个工厂仅仅能提供一个或一类产品,当产品种类较多,形成产品系列(比方我们要创建跨平台的button,菜单,文本框等等一系列GUI控件:
     
     单纯使用工厂模式会产生大量工厂,并且后期维护也不方便,我们能够从产品中找到规律,假设产品等级相对固定,以后仅仅会新增产品族,那么我们就能够把整个产品族放到一个工厂创建,以后新增其它系统产品族也很方便,例如以下图:
     
     这样的模式就是抽象工厂,工厂方法模式针对的是一个产品等级结构,而抽象工厂模式则须要面对多个产品等级结构,一个工厂等级结构能够负责多个不同产品等级结构中的产品对象的创建 。

2、结构与类图

     通用类图例如以下:
     文字开头那个创建GUI的样例类图例如以下,此处仅仅创建了Button和TextArea:

     
     产品类和接口代码例如以下(为了演示方便,省略逻辑等等):
interface Button {

}

interface TextArea {

}

class WindowButton implements Button {

}

class LinuxButton implements Button {

}

class WindowTextArea implements TextArea {

}

class LinuxTextArea implements TextArea {

}
     工厂类代码:
public interface IGuiFactory {
    // 产品Button创建方法
    Button createButton();

    // 产品TextArea创建方法
    TextArea createTextArea();

    // 有n个产品等级,就n个创建方法
}

class LinuxGuiFactory implements IGuiFactory {

    @Override
    public Button createButton() {
        return new LinuxButton();
    }

    @Override
    public TextArea createTextArea() {
        return new LinuxTextArea();
    }
}

class WindowsGuiFactory implements IGuiFactory {

    @Override
    public Button createButton() {
        return new WindowButton();
    }

    @Override
    public TextArea createTextArea() {
        return new WindowTextArea();
    }

}
      client代码:
public class Client {

    public static void main(String[] args) {
        // 为了演示,使用new方式创建工厂,最好做成单例的或先初始化好
        IGuiFactory factory = new WindowsGuiFactory();
        Button button = factory.createButton();
        TextArea textArea = factory.createTextArea();
        System. out.println(button);
        System. out.println(textArea);
    }
}
     有多少个产品族,就创建多少个工厂实现,有多少个产品等级,工厂中就要对外提供多少个创建产品方法。

3、适用场景及效果(优缺点)

     事实上工厂模式的长处,抽象工厂基本都有的,这里说说抽象工厂特有的长处:
     1、约束产品族内部元素,能够控制产品族内部各产品间关系,数量等,比方产品族内的产品有A、B,须要生产1个A时生成2个B,此时由于他们都在一个工厂实现类中,所以很easy控制。
     2、扩展产品族和工厂很easy,比方上面样例中要扩展一类系统GUI,比方说android的,添加?一套GUI控件和android的控件工厂即可。
     3、降低client推断,当一个产品族中的产品放到一起工作时,抽象工厂能确保client始终仅仅是用同一个产品族中的产品,而不用依据当前环境推断使用哪个产品了,比方使用了WindowsGuiFactory,使用控件时,client全然不用推断是哪种操作系统了,仅仅须要用WindowsGuiFactory获取即可了。
     缺点也是显而易见的,最大缺点就是扩展产品等级很困难,还是上面的样例,要新增一种控件,要把全部的工厂都要加一个方法,严重违反了开闭原则,改动接口,全部client代码也要影响,所以抽象工厂一定要确保产品等级无变化或很少的变化。
     事实上这也是设计上的一种权衡,有的时候要想让一方面扩展、使用很easy,就会导致还有一方面很难扩展,假设业务上有这种倾斜性,我们就能够做这种设计,没有绝对好的设计,仅仅有适合的设计。
     适用场景,当系统所提供的工厂所需生产的详细产品并非一个简单的对象,而是多个位于不同产品等级结构中属于不同类型的详细产品时我们会考虑使用抽象工厂模式。结合上面的优缺点,举几个详细的适用场景:
     1、系统中有1个或多个产品族时,而每次仅仅是用1个产品族,如有些桌面程序须要更换主题,皮肤等功能;
     2、系统提供一个产品类的库时,全部产品以接口方式出现,能够考虑使用抽象工厂;
     3、系统同一类产品族要放到一起使用,关联到一起这样的约束最好在设计中体现,能够使用抽象工厂。

4、模式扩展

     1、工厂模式转化,当产品等级仅仅有1个时,抽象工厂能够退化成普通工厂,假设实现比較简单,产品类不多时,普通工厂退化成简单工厂。
     2、工厂组合,抽象工厂、普通工厂当产品过多时,都会生成非常多工厂类,能够考虑使用简单工厂再将工厂类封装一下,client获取工厂时也会更方便。事实上,工厂模式是程序中用的最广的一种模式,常常和其它模式组合使用,没有哪个模式能100%使用某个环境,仅仅有模式的灵活变通,多模式混合才会产生优秀的设计。