MyException - 我的异常网
当前位置:我的异常网» 设计模式 » 悟空形式-java-抽象工厂模式

悟空形式-java-抽象工厂模式

www.MyException.Cn  网友分享于:2013-10-19  浏览:0次
悟空模式-java-抽象工厂模式

【一朝,王母娘娘设宴,大开宝阁,瑶池中做蟠桃胜会】

有一天,王母娘娘要在瑶池办party,就需要准备大量的食材。要知道,天上的神仙也分三六九等,九曜星、五方将、二十八宿、四大天王、十二元辰、五方五老、普天星相、河汉群神等等,不同等级的神仙在宴会中吃的东西也不一样。

为了方便管理,我们把神仙分为低级神仙、中级神仙和高级神仙,不同等级的神仙将领取到对应等级的食物,所以就有了低级神仙食物、中级神仙食物和高级神仙食物。

在前面的悟空模式-java-普通工厂模式悟空模式-java-工厂方法模式中都介绍了低级蟠桃(三千年)、中级蟠桃(六千年)和高级蟠桃(九千年),虽然是蟠桃盛会,但也总不能光吃蟠桃,所以由兜率宫拿出了一批仙丹,分为低级仙丹(炼三三得九天)、中级仙丹(炼七七四十九天)和高级仙丹(炼九九八十一天)。

以上,就是我们本次演示抽象工厂模式所需要的产品元素。

在前面我们说过,当产品越来越多,会使得工厂越来越难管理,要么工厂的数量越来越多,要么工厂本身越来越复杂,所以,这里介绍了抽象工厂模式,用于产生较为复杂的产品结构下的工厂,它与工厂方法最基本的区别是抽象工厂模式能够创建不同种类的产品,也就能够更加方便地基于抽象的概念管理一大堆复杂的产品对象。

首先我们介绍两个概念:产品族与产品等级。

所谓产品族,就是由功能相关联的不同种类产品组成的家族,比如我们最终所需要的低级神仙食物,它是由低级蟠桃与低级仙丹组成的。而产品等级就是对于某一种类的产品,内部划分的等级结构,如蟠桃内部被划分为低级、中级与高级,产品等级是面向同一种类的产品的内部区别描述。

在一开始,我们需要创建一个抽象工厂,这个抽象工厂中描述了每个具体工厂需要提供哪些实现。然后针对每一个产品族创建一个工厂,用于统一创建不同类型的产品。类图如下:

从图中可以看到,不同等级的产品交给了不同的工厂去创建,用户只需要调用自己的目标产品族对应的工厂,获取最终的产品族即可,至于这个产品系列内部结构如何变化,用户并不需要关心。接下来是具体的实现:

蟠桃

package com.tirion.design.abstraction.factory;

public interface FlatPeach {

    void printLevel();

    void printCycleTime();
}

低级蟠桃

package com.tirion.design.abstraction.factory;

public class LowLevelFlatPeach implements FlatPeach {

    LowLevelFlatPeach(){
        printCycleTime();
        printLevel();
    }

    @Override
    public void printLevel() {
        System.out.println("低级蟠桃");
    }

    @Override
    public void printCycleTime() {
        System.out.println("三千年一熟");
    }

}

中级蟠桃

package com.tirion.design.abstraction.factory;

public class MiddleLevelFlatPeach implements FlatPeach {

    MiddleLevelFlatPeach(){
        printCycleTime();
        printLevel();
    }

    @Override
    public void printLevel() {
        System.out.println("中级蟠桃");
    }

    @Override
    public void printCycleTime() {
        System.out.println("六千年一熟");
    }

}

高级蟠桃

package com.tirion.design.abstraction.factory;

public class HighLevelFlatPeach implements FlatPeach {

    HighLevelFlatPeach(){
        printCycleTime();
        printLevel();
    }

    @Override
    public void printLevel() {
        System.out.println("高级蟠桃");
    }

    @Override
    public void printCycleTime() {
        System.out.println("九千年一熟");
    }

}

仙丹

package com.tirion.design.abstraction.factory;

public interface Elixir {

    void printLevel();

    void printCycleTime();
}

低级仙丹

package com.tirion.design.abstraction.factory;

public class LowLevelElixir implements Elixir {

    LowLevelElixir(){
        printCycleTime();
        printLevel();
    }

    @Override
    public void printLevel() {
        System.out.println("低级仙丹");
    }

    @Override
    public void printCycleTime() {
        System.out.println("炼三三得九天");
    }

}

中级仙丹

package com.tirion.design.abstraction.factory;

public class MiddleLevelElixir implements Elixir {

    MiddleLevelElixir(){
        printCycleTime();
        printLevel();
    }

    @Override
    public void printLevel() {
        System.out.println("中级仙丹");
    }

    @Override
    public void printCycleTime() {
        System.out.println("炼七七四十九天");
    }

}

高级仙丹

package com.tirion.design.abstraction.factory;

public class HighLevelElixir implements Elixir {

    HighLevelElixir(){
        printCycleTime();
        printLevel();
    }

    @Override
    public void printLevel() {
        System.out.println("高级仙丹");
    }

    @Override
    public void printCycleTime() {
        System.out.println("炼九九八十一天");
    }

}

抽象工厂-神仙食物工厂

package com.tirion.design.abstraction.factory;

public interface XianFoodFactory {

    FlatPeach prepareFlatPeach();

    Elixir prepareElixir();

}

低级神仙食物工厂

package com.tirion.design.abstraction.factory;

public class LowLevelXianFoodFactory implements XianFoodFactory {

    @Override
    public FlatPeach prepareFlatPeach() {
        return new LowLevelFlatPeach();
    }

    @Override
    public Elixir prepareElixir() {
        return new LowLevelElixir();
    }


}

中级神仙食物工厂

package com.tirion.design.abstraction.factory;

public class MiddleLevelXianFoodFactory implements XianFoodFactory {

    @Override
    public FlatPeach prepareFlatPeach() {
        return new MiddleLevelFlatPeach();
    }

    @Override
    public Elixir prepareElixir() {
        return new MiddleLevelElixir();
    }


}

高级神仙食物工厂

package com.tirion.design.abstraction.factory;

public class HighLevelXianFoodFactory implements XianFoodFactory {

    @Override
    public FlatPeach prepareFlatPeach() {
        return new HighLevelFlatPeach();
    }

    @Override
    public Elixir prepareElixir() {
        return new HighLevelElixir();
    }


}

王母娘娘-调用者

package com.tirion.design.abstraction.factory;


public class TheQueenMother {

    public static void prepareXianFood(XianFoodFactory xianFoodFactory) {
        xianFoodFactory.prepareFlatPeach();
        xianFoodFactory.prepareElixir();
    }

    public static void main(String[] args) {
        System.out.println("准备低级神仙食物...");
        TheQueenMother.prepareXianFood(new LowLevelXianFoodFactory());
        System.out.println("准备中级神仙食物...");
        TheQueenMother.prepareXianFood(new MiddleLevelXianFoodFactory());
        System.out.println("准备高级神仙食物...");
        TheQueenMother.prepareXianFood(new HighLevelXianFoodFactory());
    }
}

代码执行结果

准备低级神仙食物...
三千年一熟
低级蟠桃
炼三三得九天
低级仙丹
准备中级神仙食物...
六千年一熟
中级蟠桃
炼七七四十九天
中级仙丹
准备高级神仙食物...
九千年一熟
高级蟠桃
炼九九八十一天
高级仙丹

使用了抽象工厂模式之后,在面对复杂的宴会菜单对象时,王母娘娘不需要关心天宫的御厨如何搭配食物,只需要下达命令要求御厨准备不同等级的食物套餐就可以了。

每个具体工厂只需要创建自己负责的产品,这符合单一职责原则。

具体工厂返回的产品是产品的抽象而不是具体,所以符合依赖导致原则。

关于开闭原则,抽象工厂模式是一个比较典型的例子。

我们在使用中可以发现,如果要添加一个新的产品族,比如王母娘娘专享食物套餐,套餐内容是高级蟠桃,而并不需要吃仙丹(王母娘娘吃仙丹已经没啥用了),那么我们只需要增加一个TheQueenMotherFoodFactory,然后在内部添加具体的实现即可,并不需要更改其他任何类,很完美地符合了开闭原则。

王母娘娘食物工厂

package com.tirion.design.abstraction.factory;

public class TheQueenMotherFoodFactory implements XianFoodFactory {

    @Override
    public FlatPeach prepareFlatPeach() {
        return new HighLevelFlatPeach();
    }

    @Override
    public Elixir prepareElixir() {
        return null;
    }


}

但是如果某一天,镇元大仙上供了一批人参果,王母娘娘一高兴,把人参果也作为宴会的一道主菜,那么就麻烦了:不仅仅抽象工厂XianFoodFactory要增加人参果的接口,它的所有实现都要增加相应的接口实现,整个体系才能继续运转下去。这时候,抽象工厂模式又不符合开闭原则了。

根据以上描述我们可以得出,对于抽象工厂模式,增加产品族符合开闭原则,增加产品种类则不符合开闭原则,也就是说抽象工厂模式具备开闭原则的倾斜性。

注意:抽象工厂模式并不是比工厂方法模式更加高级的模式,而是为了适应不同的业务变化情况而做出的不同应对,继而产生的不同解决方案而已。

抽象工厂模式的使用情景:

1.系统中存在多个产品族,用户只关心产品族,也就是只关心最终结果

2.属于同一产品族的产品相互之间具有关联关系,它们是被组合在一起使用的

抽象工厂模式遵循的设计原则:

1.依赖倒置原则(客户端依赖的是产品抽象而不是具体产品)

2.迪米特法则

3.里氏替换原则

4.接口隔离原则(使用了多个相互隔离的接口,降低了耦合度)

5.单一职责原则(每个工厂只要负责创建自己对应产品族的产品)

6.开闭原则(具有倾斜性,支持新增产品族,但不支持新增产品类型)

关于抽象工厂模式的介绍就到这里,你可以将它记忆为蟠桃宴会模式

如果你认为文章中哪里有错误或者不足的地方,欢迎在评论区指出,也希望这篇文章对你学习java设计模式能够有所帮助。转载请注明,谢谢。

更多设计模式的介绍请到悟空模式-java设计模式中查看。

文章评论

每天工作4小时的程序员
每天工作4小时的程序员
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
要嫁就嫁程序猿—钱多话少死的早
要嫁就嫁程序猿—钱多话少死的早
“懒”出效率是程序员的美德
“懒”出效率是程序员的美德
那些争议最大的编程观点
那些争议最大的编程观点
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
Google伦敦新总部 犹如星级庄园
Google伦敦新总部 犹如星级庄园
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
程序员必看的十大电影
程序员必看的十大电影
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
代码女神横空出世
代码女神横空出世
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
程序员的鄙视链
程序员的鄙视链
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
Web开发者需具备的8个好习惯
Web开发者需具备的8个好习惯
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
为什么程序员都是夜猫子
为什么程序员都是夜猫子
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
一个程序员的时间管理
一个程序员的时间管理
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
Java程序员必看电影
Java程序员必看电影
 程序员的样子
程序员的样子
如何成为一名黑客
如何成为一名黑客
中美印日四国程序员比较
中美印日四国程序员比较
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
编程语言是女人
编程语言是女人
老程序员的下场
老程序员的下场
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
我的丈夫是个程序员
我的丈夫是个程序员
10个调试和排错的小建议
10个调试和排错的小建议
总结2014中国互联网十大段子
总结2014中国互联网十大段子
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
程序员和编码员之间的区别
程序员和编码员之间的区别
程序员应该关注的一些事儿
程序员应该关注的一些事儿
漫画:程序员的工作
漫画:程序员的工作
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
程序员都该阅读的书
程序员都该阅读的书
我是如何打败拖延症的
我是如何打败拖延症的
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
2013年美国开发者薪资调查报告
2013年美国开发者薪资调查报告
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有