前言

本程序改编自《Head First Design Patterns》(简称HF )中的关于Pizza的例子(可以在GitHub下载)。


图:HF 上的抽象工厂类图。Client位于图右上角。AbstractProductA的一个子类和AbstractProductB的一个子类,两个子类合在一起构成一个产品族,即 a family of products

HF 上面的例子的Client是一个抽象类,及其子类;然后又用了一个工厂方法模式,封装了new Client( )的过程。我觉得这样子没有必要,于是把书上的例子做了简化:把Client改成普通类;然后再用一个简单工厂封装new Client( )的过程。这样子丝毫不影响抽象工厂的精髓,反而还可以简化代码,突出重点。

PS. 实验楼网站里面的例子中,Client是一个普通类,没有用简单工厂或者工厂方法模式封装Client。我觉得这样子不好,因为这样直接把”Client的new的过程“暴露在Main里面了。

抽象工厂模式,可以和简单工厂或者工厂方法模式“组合在一起”,让后两者进一步封装抽象工厂中的Client。


严格的类图

总共14个java文件

  • 两个抽象产品接口
  • 四个具体产品类
  • 一个抽象工厂接口
  • 四个具体工厂类
  • 一个Client类
  • 一个封装Client类的简单工厂
  • 一个Main类


图:我绘制的类图,严格的抽象工厂模式类图(一些资料不区分聚合、关联、依赖,把这三种关系统统当作依赖关系)。我使用了一个叫做AmaterasUML 的插件。


Talk is cheap, show me the code

两个抽象产品接口

package abstractFactory;// 抽象产品A——蔬菜
public interface Veggies {public String toString();
}
package abstractFactory;// 抽象产品B——肉馅
public interface Meat {public String toString();
}

四个具体产品类

package abstractFactory;// 具体产品A1——白菜
public class Cabbage implements Veggies
{public String toString(){return "白菜";}
}
package abstractFactory;// 具体产品A2——青椒
public class GreenPepper implements Veggies
{public String toString(){return "青椒";}
}
package abstractFactory;// 具体产品B1——猪肉馅
public class Pork implements Meat {public String toString(){return "猪肉";}
}
package abstractFactory;// 具体产品B2——牛肉馅
public class Beaf implements Meat
{public String toString(){return "牛肉";}
}

一个抽象工厂接口

package abstractFactory;// 工厂接口
public interface BaoZiIngredientFactory
{public abstract Veggies createVeggies();   // 蔬菜类产品public abstract Meat    createMeat();      // 肉类产品
}

四个具体工厂类

package abstractFactory;// 具体工厂1生产的白菜猪肉包子
public class BaoZiIngredientFactory1 implements BaoZiIngredientFactory
{@Overridepublic Veggies createVeggies(){return new Cabbage(); // A1}@Overridepublic Meat createMeat(){return new Pork();    // B1}}
package abstractFactory;// 具体工厂2生产的白菜牛肉包子
public class BaoZiIngredientFactory2 implements BaoZiIngredientFactory
{@Overridepublic Veggies createVeggies(){return new Cabbage(); // A1}@Overridepublic Meat createMeat(){return new Beaf();    // B2 }}
package abstractFactory;// 具体工厂3生产的青椒牛肉包子
public class BaoZiIngredientFactory3 implements BaoZiIngredientFactory
{@Overridepublic Veggies createVeggies(){return new GreenPepper(); // A2}@Overridepublic Meat createMeat(){return new Beaf();        // B2}}
package abstractFactory;//具体工厂4生产的青椒猪肉包子
public class BaoZiIngredientFactory4 implements BaoZiIngredientFactory
{@Overridepublic Veggies createVeggies(){return new GreenPepper();  // A2}@Overridepublic Meat createMeat(){return new Pork();         // B1}}

一个Client

package abstractFactory;// Client即包子,聚合两个抽象产品,关联工厂接口
public class BaoZi
{String name;// 一个包子就是一个"a family of products"// 一个包子由分布在两类抽象产品中的三个具体产品构成Veggies veggies; // A类产品-蔬菜馅Meat    meat;    // B类产品-肉馅BaoZiIngredientFactory factory; // 工厂接口public BaoZi(){// 构造函数都不做什么事}public void setIngredientFactory(BaoZiIngredientFactory factory){this.factory = factory;}public void makeBaoZi(){prepare();  // 准备原材料steam();    // 蒸30分钟setName(veggies.toString() + meat.toString() + "包子");}void prepare(){veggies = factory.createVeggies();meat    = factory.createMeat();System.out.println("Preparing " + veggies.toString() + "," + meat.toString());}void steam(){System.out.println("Steam for 30 minutes");}void setName(String name){this.name = name;}String getName(){return name;}public String toString(){StringBuffer result = new StringBuffer();result.append("---- " + name + " ----\n");if (veggies != null){result.append(veggies);result.append("馅 + ");}if (meat != null){result.append(meat);result.append("馅\n");}return result.toString();}
}

一个封装Client类的简单工厂

抽象工厂可以结合简单工厂,当然也可以结合工厂方法模式,用来封装new Client( ) 的过程。简单工厂的本质是:依据传入的参数,决定生产,然后return哪一个new BaoZi(产品族, a family of products)

package abstractFactory;public class BaoZiStore
{protected  BaoZi createBaoZi(String baoZiName){BaoZi baoZi = new BaoZi();BaoZiIngredientFactory factory = null;if(baoZiName.equals("白菜猪肉")){factory = new BaoZiIngredientFactory1();baoZi.setIngredientFactory(factory);}else if(baoZiName.equals("白菜牛肉")){factory = new BaoZiIngredientFactory2();baoZi.setIngredientFactory(factory);}else if(baoZiName.equals("青椒牛肉")){factory = new BaoZiIngredientFactory3();baoZi.setIngredientFactory(factory);}else if(baoZiName.equals("青椒猪肉")){factory = new BaoZiIngredientFactory4();baoZi.setIngredientFactory(factory);}return baoZi;}public BaoZi orderBaoZi(String baoZiName){BaoZi baoZi = createBaoZi(baoZiName);baoZi.makeBaoZi();return baoZi;}
}

一个Main类

package abstractFactory;public class Main
{public static void main(String[] args){BaoZiStore baoZiStore = new BaoZiStore();BaoZi baoZi = null;baoZi = baoZiStore.orderBaoZi("白菜猪肉");System.out.println(baoZi);baoZi = baoZiStore.orderBaoZi("白菜牛肉");System.out.println(baoZi);baoZi = baoZiStore.orderBaoZi("青椒牛肉");System.out.println(baoZi);baoZi = baoZiStore.orderBaoZi("青椒猪肉");System.out.println(baoZi);}   }

运行结果

直接从eclipse复制过来

Preparing 白菜,猪肉
Steam for 30 minutes
---- 白菜猪肉包子 ----
白菜馅 + 猪肉馅Preparing 白菜,牛肉
Steam for 30 minutes
---- 白菜牛肉包子 ----
白菜馅 + 牛肉馅Preparing 青椒,牛肉
Steam for 30 minutes
---- 青椒牛肉包子 ----
青椒馅 + 牛肉馅Preparing 青椒,猪肉
Steam for 30 minutes
---- 青椒猪肉包子 ----
青椒馅 + 猪肉馅

抽象工厂模式和工厂方法模式的差别

代码层面:
工厂方法模式:工厂抽象类,几个工厂子类继承这个抽象类,工厂子类new Product() ,任务完成。
抽象工厂模式:工厂接口,几个工厂子类实现这个接口,工厂子类new 很多 Products(),但是任务还没完。

我们需要的是”a family of Products”(产品族)。此时需要引入新的角色,Client。这个Client关联工厂子类,把工厂子类new出来的所有Products聚合起来,形成一个产品族。然后再把这个产品族,看成”一个大产品“(我的代码中的包子)。为了让这个”大产品(包子)的new的过程“不至于直接暴露在Main类中,把这个大产品封装在一个简单工厂里面(或者HF 封装在工厂方法模式里面)。此时任务才完成~~

需求层面:
直接引用HF 里面的原话,原话已经不能够再简练了。。。
Abstract Factory: Remember me, Abstract Factory, and use me whenever you have families of products you need to create and you want to make sure your clients create products that belong together.

Factory Method: And I’m Factory Method; use me to decouple your client code from the concrete classes you need to instantiate, or if you know ahead of time all the concrete classes you are going to need. To use me, just subclass me implement my factory method!

深入研究设计模式,猛戳这里(推荐新窗口打开)~

设计模式——抽象工厂 Java源代码相关推荐

  1. 【JAVA进阶系列】JAVA 设计模式 -- 抽象工厂模式(Abstract Factory)

    [JAVA进阶系列]JAVA 设计模式 -- 抽象工厂模式(Abstract Factory) [1.1]抽象工厂模式简介 抽象工厂者模式的类结构图 AbstractProduct(抽象产品),Abs ...

  2. 创建设计模式 - 抽象工厂设计模式

    创建设计模式 - 抽象工厂设计模式 欢迎来到java示例中的Abstract Factory Design Pattern.摘要工厂设计模式是创造模式之一.抽象工厂模式几乎类似于工厂模式,除了它更像工 ...

  3. 系统架构技能之设计模式-抽象工厂模式

    一.上篇回顾 上篇我们主要讲述了简单工厂模式和工厂模式.并且分析了每种模式的应用场景和一些优缺点,我们现在来回顾一下: 简单工厂模式:一个工厂负责所有类型对象的创建,不支持无缝的新增新的类型对象的创建 ...

  4. 常见设计模式—抽象工厂模式

    设计模式-抽象工厂模式 1.什么是抽象工厂模式 抽象工厂模式是围绕一个超级工厂创建其它工厂,是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品. 2.角色分 ...

  5. java设计模式---抽象工厂模式

    工厂模式在项目中是常常用到的,有人说只有大项目才会用到,小项目是体会不出来.其实使用设计模式与项目的大小没有实质性的联系.设计模式是经验的总结而不是衡量项目大小的标准. 以开发项目的DAO层为例,在项 ...

  6. 简单工厂和 工厂设计模式--抽象工厂模式--Java实现

    简单工厂不是23种设计模式 工厂方法·模式 :定义一个创建对象得接口,但是让实现这个接口的类来决定实例化哪一个类,工厂方法能使得类的实例化推迟到子类中进行 工厂方法缺点: 增加了类的数量,增加复杂度 ...

  7. 设计模式-抽象工厂模式的应用场景及Java中对抽象工厂的应用

    1. 什么是抽象工厂模式 抽象工厂模式提供了一个创建一系列相关或者相互依赖对象的接口,无需指定他们的类 抽象工厂模式(Abstract Factory Pattern)隶属于设计模式中的创建型模式,用 ...

  8. Java设计模式——抽象工厂模式

    文章目录 抽象工厂 概念 优缺点 优点 缺点 适用场景 代码案例 抽象工厂 使用工厂方法模式足以应付我们可能遇到的大部分业务需求. 但是当产品种类非常多时,就会出现 大量的与之对应的工厂类,这不应该是 ...

  9. 程序设计之Java设计模式(抽象工厂模式)

    原文地址:http://zhangwei-david.iteye.com/blog/2187627,该文通俗易懂,实为经典! 在设计模式一书中是这样描述抽象工厂的意图的: 提供一个创建一系列相关或相互 ...

最新文章

  1. 多线程-NSOperation
  2. 我的世界1.7.10java下载安装_我的世界1.7.10正式版
  3. 转python version 2.7 required,which was not found in the registry
  4. 因子分析——因子旋转
  5. 轻松实现突破网管限制(SoftEther实际应用)
  6. 隐藏/显示jeecg-boot 后端管理页面的右侧的系统设置
  7. emacs .emacs_使用Emacs进行社交并跟踪您的待办事项列表
  8. 一段代码把网站变成灰白色
  9. 轮播 一张中间 两张在旁边_黄渤为《五哈》做海报,邓超陈赫都只有一张,唯独对鹿晗待遇不同...
  10. 高性能加速深度学习算法
  11. 开课吧:深入了解人工智能在金融行业中的应用
  12. 网站压力测试工具webbench使用说明
  13. document.execCommand() 命令详解 只支持IE
  14. 微信里的 Office 365 —— Office 365 微助理打造移动办公新体验
  15. Vue学习记录(三)——脚手架的使用和Vuex
  16. 战国七雄中最强大的国家(除秦外)——赵国_我是亲民_新浪博客
  17. PKUSC 2018 旅游记
  18. 微信小程序旋转动画,图片转动view旋转等
  19. matlab图片修复原理,图像修复 Region filling and object removal by exemplar-based image inpainting matlab实现...
  20. 用python制作网盘_3分钟教你用python制作一个简单词云

热门文章

  1. encode() decode() 编码解码函数
  2. Ubuntu虚拟机中网络中没有网卡
  3. MATLAB远程桌面不可启动——解决方法
  4. Navicat还原nb3备份文件步骤
  5. matlab输入符号怎么打,matlab 输入符号
  6. R语言学习记录:unique()函数
  7. 关于项目部署在Tomcat中使用软连接之坑
  8. 【owt-server】 只sync webrtc-m79并构建
  9. 如何进行网站seo优化推广?
  10. Android网络代理原理及实现