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

来源:互联网 发布:php文章评论代码 编辑:程序博客网 时间:2024/06/07 23:15
1、动机与定义

     工厂模式中,一个工厂只能提供一个或一类产品,当产品种类较多,形成产品系列(比如我们要创建跨平台的按钮,菜单,文本框等等一系列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();    }}
      客户端代码:
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,此时因为他们都在一个工厂实现类中,所以非常容易控制。
     2、扩展产品族和工厂非常容易,比如上面例子中要扩展一类系统GUI,比如说android的,增加一套GUI控件和android的控件工厂就行。
     3、减少客户端判断,当一个产品族中的产品放到一起工作时,抽象工厂能确保客户端始终只是用同一个产品族中的产品,而不用根据当前环境判断使用哪个产品了,比如使用了WindowsGuiFactory,使用控件时,客户端完全不用判断是哪种操作系统了,只需要用WindowsGuiFactory获取就行了。
     缺点也是显而易见的,最大缺点就是扩展产品等级非常困难,还是上面的例子,要新增一种控件,要把所有的工厂都要加一个方法,严重违反了开闭原则,修改接口,所有客户端代码也要影响,所以抽象工厂一定要确保产品等级无变化或非常少的变化。
     其实这也是设计上的一种权衡,有的时候要想让一方面扩展、使用非常容易,就会导致另一方面非常难扩展,如果业务上有这样的倾斜性,我们就可以做这种设计,没有绝对好的设计,只有适合的设计。
     适用场景,当系统所提供的工厂所需生产的具体产品并不是一个简单的对象,而是多个位于不同产品等级结构中属于不同类型的具体产品时我们会考虑使用抽象工厂模式。结合上面的优缺点,举几个具体的适用场景:
     1、系统中有1个或多个产品族时,而每次只是用1个产品族,如有些桌面程序需要更换主题,皮肤等功能;
     2、系统提供一个产品类的库时,所有产品以接口方式出现,可以考虑使用抽象工厂;
     3、系统同一类产品族要放到一起使用,关联到一起这种约束最好在设计中体现,可以使用抽象工厂。

4、模式扩展

     1、工厂模式转化,当产品等级只有1个时,抽象工厂可以退化成普通工厂,如果实现比较简单,产品类不多时,普通工厂退化成简单工厂。
     2、工厂组合,抽象工厂、普通工厂当产品过多时,都会生成很多工厂类,可以考虑使用简单工厂再将工厂类封装一下,客户端获取工厂时也会更方便。其实,工厂模式是程序中用的最广的一种模式,经常和其他模式组合使用,没有哪个模式能100%使用某个环境,只有模式的灵活变通,多模式混合才会产生优秀的设计。
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 高中被学校开除怎么办 bois密码忘记了怎么办 xp系统管理员账号停用怎么办 学业负担太重怎么办 小学生手册丢了怎么办 自己不会写论文怎么办 写论文很心慌怎么办 写论文没有词怎么办 亲人入了邪教怎么办 小孩脾气很倔怎么办 研究生读不下去怎么办 国外打工生活费不够怎么办 本科学位被追回怎么办 本科学位丢了怎么办 国外留学挂科怎么办 英国预科被劝退怎么办? 如果预科没合格怎么办 研究生学费太贵怎么办 澳洲移民配额用不完怎么办 去美国探亲怎么办签证 去伊朗的签证怎么办 房产证被偷了怎么办 打黑工被发现怎么办 几年前被犬咬没打针怎么办 对狂犬疫苗过敏怎么办 想去墨尔本留学怎么办 大学没交学费会怎么办 交学费收据丢了怎么办 上海浦东金科苑幼儿园统筹怎么办 红酒瓶塞掉了怎么办 红酒瓶塞丢了怎么办 收入证明没有公章怎么办 父母没工作怎么办签证 在温哥华怎么办新西兰签证 上班第一天无聊怎么办 上班紧张不自信怎么办 销售到了30岁怎么办 转行会计没经验怎么办 澳洲coe被取消怎么办 父母不同意嫁远怎么办 家人不同意我们在一起怎么办