浅析设计模式(三)——抽象工厂模式
抽象工厂模式(Abstract-Factory,创建型模式)
本文的结构:
- 一、抽象工厂模式的定义
- 二、抽象工厂模式的参与者及其角色
- 三、抽象工厂模式的类图
- 四、抽象工厂模式的示例
- 五、参考
一、抽象工厂模式的定义
提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
前面【浅析设计模式(四)——创建型模式之Simple-Factory(简单工厂方法,非设计模式)】中介绍的简单工厂方法,虽然已经对变化的部分进行了封装,但是这里只由一个对象负责所有的具体类的实例化,因此每次有新增对象类型时,都需要改变工厂的源码进行扩展。而【浅析设计模式(五)——创建型模式之Factory-Method(工厂方法模式)】中介绍的工厂方法模式,则对简单工厂方法进行了最直接的封装和抽象,把创建对象的具体操作进行了分离,便于扩展和维护。这两种做法都是用于创建单类对象。
从某种角度来看,抽象工厂模式也是类似的,都是把创建对象的动作进行了封装。但是抽象工厂模式意在创建相关或依赖对象的家族。从抽象工厂模式的实现来看,它通过组合委托给具体的工厂来实现,对象的创建被实现在工厂接口所暴露出来的方法中,通常用于创建产品家族或者相关集合。而这些工厂通常使用工厂方法来实现具体的产品创建。做个最简化,如果抽象工厂也只是创建一类产品,而不考虑后续的扩展之类的,是可以直接用工厂方法来实现的。
这里有必要对“相关或依赖对象的家族”做一个简单地说明,举个栗子,假如要创建的对象是台电脑,那么像键盘、鼠标、显示器、主机等等,就可以看成是“相关或依赖对象的家族”。下面要举的栗子也是类似的,也还是拿Pizza的例子,Pizza有各种原料,这里从简,只举出Cheese奶酪、Veggies蔬菜、Clams蛤等原料进行说明,这里的创建对象,实际上是创建了包含各类原料的Pizza,也即就是提到的“相关或依赖对象的家族”。
二、抽象工厂模式的参与者及其角色
1. AbstractFactory
- 声明一个创建抽象产品对象的操作接口
2. ConcreteFactory
- 实现创建具体产品对象的操作
3. AbstractProduct
- 为一类产品对象声明一个接口
4. ConcreteProduct
- 定义一个将被相应的具体工厂创建的产品对象
- 实现AbstractProduct接口
5. Client
- 仅使用由AbstractFactory和AbstractProduct类声明的接口。
三、抽象工厂模式的类图
四、抽象工厂模式的示例
1. AbstractFactory:声明一个创建抽象产品对象的操作接口,用于创建相关或依赖对象的家族。
1 /** 2 * 3 * <p> 4 * Reference : Head-First-Design-Patterns 5 * 6 */ 7 public interface PizzaIngredientFactory { 8 public Cheese createCheese(); 9 public Veggies[] createVeggies(); 10 public Clams createClam(); 11 }
2. ConcreteFactory:实现创建具体产品对象的操作,这里就是最简单的直接创建对象,
例1:
1 /** 2 * 3 * <p> 4 * Reference : Head-First-Design-Patterns 5 * 6 */ 7 public class NYPizzaIngredientFactory implements PizzaIngredientFactory{ 8 9 @Override 10 public Veggies[] createVeggies() { 11 Veggies veggies[] = { new Garlic(), new Onion(), new Mushroom()}; 12 return veggies; 13 } 14 15 @Override 16 public Clams createClam() { 17 return new FreshClams(); 18 } 19 20 @Override 21 public Cheese createCheese() { 22 return new ReggianoCheese(); 23 } 24 }
例2
1 /** 2 * 3 * <p> 4 * Reference : Head-First-Design-Patterns 5 * 6 */ 7 public class ChicagoPizzaIngredientFactory implements PizzaIngredientFactory{ 8 9 @Override 10 public Cheese createCheese() { 11 return new MozzarellaCheese(); 12 } 13 @Override 14 public Veggies[] createVeggies() { 15 Veggies veggies[] = { new Onion(), new Garlic()}; 16 return veggies; 17 } 18 @Override 19 public Clams createClam() { 20 return new FrozenClams(); 21 } 22 }
从这里可以看出,上面的具体工厂其实就是工厂方法的简化,不带任何判断就直接创建了具体的对象。当然也是可以像前面提到的工厂方法模式一样,带参数,然后根据参数进行具体对象的创建。
3. AbstractProduct:为一类产品对象声明一个接口,以上创建的“相关或依赖对象的家族”其实就是这里需要用到的。
1 /** 2 * 3 * <p> 4 * Reference : Head-First-Design-Patterns 5 * 6 */ 7 public abstract class Pizza { 8 String name; 9 10 Veggies veggies[]; 11 Cheese cheese; 12 Clams clam; 13 14 abstract void prepare(); 15 16 void bake() { 17 System.out.println("Bake for 25 minutes at 350"); 18 } 19 20 void cut() { 21 System.out.println("Cutting the pizza into diagonal slices"); 22 } 23 24 void box() { 25 System.out.println("Place pizza in official PizzaStore box"); 26 } 27 28 void setName(String name) { 29 this.name = name; 30 } 31 32 String getName() { 33 return name; 34 } 35 36 public String toString() { 37 StringBuffer result = new StringBuffer(); 38 result.append("---- " + name + " ----\n"); 39 40 if (cheese != null) { 41 result.append(cheese); 42 result.append("\n"); 43 } 44 if (veggies != null) { 45 for (int i = 0; i < veggies.length; i++) { 46 result.append(veggies[i]); 47 if (i < veggies.length-1) { 48 result.append(", "); 49 } 50 } 51 result.append("\n"); 52 } 53 if (clam != null) { 54 result.append(clam); 55 result.append("\n"); 56 } 57 return result.toString(); 58 } 59 }
4. ConcreteProduct:实现AbstractProduct接口,定义一个将被相应的具体工厂创建的产品对象。
这里简单地举个栗子即可,可以看到,这里组合使用了创建对象的工厂,然后根据需要由工厂创建具体的对象。
1 /** 2 * 3 * <p> 4 * Reference : Head-First-Design-Patterns 5 * 6 */ 7 public class VeggiePizza extends Pizza{ 8 PizzaIngredientFactory ingredientFactory; 9 10 public VeggiePizza(PizzaIngredientFactory ingredientFactory) { 11 this.ingredientFactory = ingredientFactory; 12 } 13 14 @Override 15 void prepare() { 16 System.out.println("Preparing " + name); 17 cheese = ingredientFactory.createCheese(); 18 veggies = ingredientFactory.createVeggies(); 19 } 20 }
类似的
1 /** 2 * 3 * <p> 4 * Reference : Head-First-Design-Patterns 5 * 6 */ 7 public class ClamPizza extends Pizza{ 8 PizzaIngredientFactory ingredientFactory; 9 10 public ClamPizza(PizzaIngredientFactory ingredientFactory) { 11 this.ingredientFactory = ingredientFactory; 12 } 13 14 void prepare() { 15 System.out.println("Preparing " + name); 16 cheese = ingredientFactory.createCheese(); 17 clam = ingredientFactory.createClam(); 18 } 19 }
5. Client:仅使用由AbstractFactory和AbstractProduct类声明的接口。
这里的例子曲折了点,不过也可以大概说明要表达的意思。获取到具体Pizza的流程如下:
- 首先创建一个纽约披萨店,即PizzaStore nyStore = new NYPizzaStore();
- 通过披萨店下订单,即Pizza pizza = nyStore.orderPizza("cheese");
- orderPizza("cheese")首先调用Pizza pizza = createPizza("cheese");
- createPizza("cheese")中就涉及到了具体的工厂类,pizza = new CheesePizza(ingredientFactory);
- 接下来就是具体的准备Pizza了,调用pizza.prepare()时,便是由工厂具体地创建所有对象家族了。如下
1 void prepare() { 2 System.out.println("Preparing " + name); 3 cheese = ingredientFactory.createCheese(); 4 //...其他的原料产品,如Veggies、Clams等,可能只需要一个,也可能全部都要。这里略去 5 }
顺着这个思路走:
PizzaStore nyStore = new NYPizzaStore() →
Pizza pizza = nyStore.orderPizza("cheese") →
Pizza pizza = createPizza("cheese") →
pizza = new CheesePizza(ingredientFactory) →
pizza.prepare() →
ingredientFactory创建具体的产品。。。
测试用的主类和主函数:
1 /** 2 * This is the test-main. 3 * <p> 4 * Reference : Head-First-Design-Patterns 5 * 6 */ 7 public class PizzaTestApp { 8 public static void main(String[] args) { 9 PizzaStore nyStore = new NYPizzaStore(); 10 PizzaStore chicagoStore = new ChicagoPizzaStore(); 11 12 Pizza pizza = nyStore.orderPizza("cheese"); 13 System.out.println("Ethan ordered a " + pizza + "\n"); 14 15 pizza = chicagoStore.orderPizza("cheese"); 16 System.out.println("Joel ordered a " + pizza + "\n"); 17 18 pizza = nyStore.orderPizza("clam"); 19 System.out.println("Ethan ordered a " + pizza + "\n"); 20 21 pizza = chicagoStore.orderPizza("clam"); 22 System.out.println("Joel ordered a " + pizza + "\n"); 23 24 25 pizza = nyStore.orderPizza("veggie"); 26 System.out.println("Ethan ordered a " + pizza + "\n"); 27 28 pizza = chicagoStore.orderPizza("veggie"); 29 System.out.println("Joel ordered a " + pizza + "\n"); 30 } 31 }
抽象类PizzaStore
1 /** 2 * 3 * <p> 4 * Reference : Head-First-Design-Patterns 5 * 6 */ 7 public abstract class PizzaStore { 8 protected abstract Pizza createPizza(String item); 9 10 public Pizza orderPizza(String type) { 11 Pizza pizza = createPizza(type); 12 System.out.println("--- Making a " + pizza.getName() + " ---"); 13 pizza.prepare(); 14 pizza.bake(); 15 pizza.cut(); 16 pizza.box(); 17 return pizza; 18 } 19 }
继承抽象类PizzaStore的具体实现类NYPizzaStore。
1 /** 2 * 3 * <p> 4 * Reference : Head-First-Design-Patterns 5 * 6 */ 7 public class NYPizzaStore extends PizzaStore{ 8 protected Pizza createPizza(String item) { 9 Pizza pizza = null; 10 PizzaIngredientFactory ingredientFactory = 11 new NYPizzaIngredientFactory(); 12 13 if (item.equals("cheese")) { 14 15 pizza = new CheesePizza(ingredientFactory); 16 pizza.setName("New York Style Cheese Pizza"); 17 18 } else if (item.equals("veggie")) { 19 20 pizza = new VeggiePizza(ingredientFactory); 21 pizza.setName("New York Style Veggie Pizza"); 22 23 } else if (item.equals("clam")) { 24 25 pizza = new ClamPizza(ingredientFactory); 26 pizza.setName("New York Style Clam Pizza"); 27 28 } 29 return pizza; 30 } 31 }
简单地总结,就是使用组合工厂类创建了包含一系列相关对象的具体产品对象。
五、参考
1、参考《Head First设计模式》和GoF《设计模式:可复用面向对象软件的基础》
2、代码可参考【github传送门】、UML类图参考【github传送门】
转载于:https://www.cnblogs.com/wpbxin/p/9237036.html
浅析设计模式(三)——抽象工厂模式相关推荐
- 设计模式三—抽象工厂模式
设计模式三-抽象工厂模式 一.定义 抽象工厂模式是工厂方法模式的进一步抽象.如果产品簇中只有一种产品,则退化为工厂方法模式. 二.原理图 三.代码实例 * 苹果和土豆是园丁1的杰作 * 葡萄和西红柿是 ...
- 设计模式之四(抽象工厂模式第三回合)
原文:设计模式之四(抽象工厂模式第三回合) 前言 抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类. 抽象工厂模式最大的好处便是易于交换产品系列,由于具体工厂类,例如I ...
- C#设计模式(4)——抽象工厂模式
C#设计模式(4)--抽象工厂模式 一.引言 在上一专题中介绍了工厂方法模式,工厂方法模式是为了克服简单工厂模式的缺点而设计出来的,简单工厂模式的工厂类随着产品类的增加需要增加额外的代码),而工厂方法 ...
- 设计模式系列·抽象工厂模式
前言 以小说的笔法写的设计模式系列文章,你绝对看得懂![首发于公众号:"聊聊代码"] 设计模式系列·王小二需求历险记(一) 设计模式系列·王小二需求历险记(二) 设计模式系列·封装 ...
- 乐在其中设计模式(C#) - 抽象工厂模式(Abstract Factory Pattern)
原文:乐在其中设计模式(C#) - 抽象工厂模式(Abstract Factory Pattern) [索引页] [源码下载] 乐在其中设计模式(C#) - 抽象工厂模式(Abstract Facto ...
- 设计模式复习-抽象工厂模式
设计模式复习-抽象工厂模式 有两种硬件,PC和Phone,有两种系统,Windows和Linux,现在假设PC和Phone上全都能安装这两个系统,并且将来硬件不会在变化,但是系统可能需要扩展,比如扩展 ...
- python抽象工厂模式_Python设计模式之抽象工厂模式
Python设计模式之抽象工厂模式 这篇文章主要为大家详细介绍了Python设计模式之抽象工厂模式,感兴趣的小伙伴们可以参考一下 python面向对象编程入门,我们需要不断学习进步 "&qu ...
- 设计模式-04抽象工厂模式
设计模式-04抽象工厂模式 文章中涉及到的代码,请自行下载 https://gitee.com/pan_xiao_lei123/designmode.git 前面介绍的工厂方法模式中考虑的是一类产品的 ...
- Java 设计模式之抽象工厂模式
抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂.该超级工厂又称为其他工厂的工厂.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 在抽 ...
最新文章
- Mysql 安装服务无法启动解决方案与使用的一般使用指令
- 破解phpstorm2017.3.1版本并解决win10下修改hosts问题
- 2.9 情感分类-深度学习第五课《序列模型》-Stanford吴恩达教授
- 只剩 1 天 | 神策 2019 数据驱动大会明天开幕
- 求1+2+……+N的和
- vscode 设置断点知乎_vscode 代码自动换行设置
- 前端学习(3317):connect 2
- opython3l_python之 数据类型判定与类型转换
- 【网络安全面试题】—如何注入攻击Java Python PHP等主流语言
- linux如何查看端口被哪个进程占用?
- NoSQL--Redis 2.4--Set
- 图的广度优先搜索算法
- JMX系列之JmxMBeanServer
- Java开源框架Netty
- 解决ubuntu克隆github上的项目速度很慢的问题
- yarn : 无法加载文件 C:\Users\L\AppData\Roaming\npm\yarn.ps1,因为在此系统上禁止运行脚本
- ubuntu添加桌面快捷方式图标
- Java 下载多个文件打成zip压缩包
- 201871010133-赵永军《面向对象程序设计(java)》第二周学习总结
- 《神经网络与深度学习》(Michael Nielsen)Neural Networks and Deep Learning习题解答汇总