浅析设计模式(六)——创建型模式之Abstract-Factory(抽象工厂模式)

抽象工厂模式Abstract-Factory

本文的套路:

  1. 抽象工厂模式的定义
  2. 抽象工厂模式的参与者及其角色
  3. 抽象工厂模式的类图
  4. 抽象工厂模式的示例
  5. 参考

抽象工厂模式的定义

  提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。

  前面【浅析设计模式(四)——创建型模式之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的流程如下:

  1. 首先创建一个纽约披萨店,即PizzaStore nyStore = new NYPizzaStore();
  2. 通过披萨店下订单,即Pizza pizza = nyStore.orderPizza("cheese");
  3. orderPizza("cheese")首先调用Pizza pizza = createPizza("cheese");
  4. createPizza("cheese")中就涉及到了具体的工厂类,pizza = new CheesePizza(ingredientFactory);
  5. 接下来就是具体的准备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

时间: 2024-10-13 02:21:33

浅析设计模式(六)——创建型模式之Abstract-Factory(抽象工厂模式)的相关文章

设计模式(一): abstract factory抽象工厂模式 -- 创建型模式

1.定义 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类. 2.适用场景 1.一个系统要独立于它的产品创建.组合和表示. 2.一个系统要由多个产品系列中的一个来配置. 3.当你要强调一系列相关的产品对象的设计以便进行联合使用. 4.当你提供一个产品类库,而只想显示它们的接口而不是实现. 3.评价 1.它分离了具体的类 2.它使得易于交换产品系列 3.它有利于产品的一致性 4.难以支持新种类的产品 5."开放-封闭"原则要求系统对扩展开放,对修改封闭.通过扩展达到增

一天一个设计模式——Abstract Factory抽象工厂模式

一.模式说明 前面学习了工厂方法(Factory Method)模式.在工厂方法模式中,在工厂方法模式中,父类决定如何生成实例,但并不决定所要生成的具体类,具体的处理交由子类来处理.这里学习的抽象工厂方法模式中,抽象工厂使用抽象的零件组装成抽象的产品.即使用包含特定的方法接口零件,将零件组装成抽象产品. 二.模式类图: 上面的类图中包含两个包:包含抽象工厂,抽象零件,抽象产品的类所在的包以及具体工厂实现类的包. 三.代码示例 1.Item类: package com.designpattern.

c++ 设计模式9 (Abstract Factory 抽象工厂模式)

5.2 抽象工厂模式 动机:在软件系统中,经常面临着"一系列相互依赖的对象"的创建工作:同时,由于需求的变化,往往存在更多系列对象的创建工作. 代码示例: 实现利用数据库的业务逻辑,支持多数据库(Sql,Oracle等),有连接.命令.读取等功能. 其中命令,连接功能之间有相互联系. 方法一(使用工厂方法): 每个功能类有一个创建的工厂,如IDBConnection与IDBConnectionFactory 1 //数据库访问有关的基类 2 class IDBConnection{ 3

Java设计模式:Abstract Factory(抽象工厂)模式

概念定义 抽象工厂(Abstract Factory)模式提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类. 抽象工厂模式中,系统的产品有多于一个的产品族(一个产品族里定义多个产品),而系统只消费其中某一族的产品.换句话说,抽象工厂创建一整套具有相互依赖或作用关系的产品(至少两个产品),而工厂方法中的工厂只能创建单一系列的产品. 应用场景 客户端不需要知道它所创建的对象的类. 需要一组对象共同完成某种功能时,并且可能存在多组对象完成不同功能的情况. 系统结构稳定,不会频繁地增加

Abstract Factory 抽象工厂模式

提供一个创建一些列相关或相互依赖对象的接口,而无需指定它们具体的类. 抽象工厂顾名思义就是对工厂的抽象,它提供了一组创建抽象产品对象的操作接口,我们实际使用的是抽象工厂的派生类,派生类中提供了操作的具体实现,创建一组具体的对象. 以下情况可以使用抽象工厂模式: 一个系统要独立于它的产品的创建.组合和表示时. 一个系统要由多个产品系列中的一个来配置时. 当你要强调一系列相关的产品对象的设计以便进行联合使用时. 当你提供一个产品类库,而只想显示它们的接口而不是实现时. 抽象工厂模式的优缺点: 他分离

[Python设计模式] 第15章 如何兼容各种DB——抽象工厂模式

github地址:https://github.com/cheesezh/python_design_patterns 题目 如何让一个程序,可以灵活替换数据库? 基础版本 class User(): """ 用户类,模拟用户表,假设只有ID和name两个字段 """ def __init__(self): self.id = None self.name = None class SqlServerUser(): ""&qu

深入浅出设计模式 ------ Abstract Factory(抽象工厂)

一. 定义  提供一个创建一系列相关或相互依赖对象的接口, 而无需指定它们的具体类. 二. 结构 三. 参与者 Product (Fruit和Leaf两个抽象产物) : 抽象生产者接口: TreeFruit(树上的水果). TreeLeaf(树上的叶子). GroundFruit(地上的水果). GroundLeaf(地上的叶子) : 实际的自然产物: NatureFactory: 抽象的自然制造工厂, 用于生产水果和叶子: TreeFactory. LeafFactory : 实际的自然制造工

终极版:由简单工厂模式,升级到抽象工厂模式(用到反射)

前面两个已经学习简单三层到简单工厂模式的变化,但是简单工厂模式还是有个缺点,就是简单工厂中集合了所有的实例的创建.也不是很好. 现在想到使用抽象工厂的方式来实现这个: 我们在程序集中加上下面的代码: <appSettings> <!--命名空间--> <add key="DALNameSpace" value="DAL"/> <!--程序集--> <add key="DALAssembly"

java进阶之工厂模式(二)抽象工厂模式

public interface KitchenFactory{ //抽象工厂 public Food getFood(); 抽象方法 public TableWare getTableWare(); } public interface Food{ //抽象食物 public String getFoodName(); } public interface TableWare{ public String getToolName(); //抽象餐具 } public class AKitche

抽象工厂模式在android中使用

抽象工厂模式(Abstract Factory) 抽象工厂模式是对象的创建模式,它是工厂方法模式的进一步延伸和拓展的结果.抽象工厂模式更加抽象化,更具一般性特点. 我们知道,工厂方法模式是针对单一的产品等级结构而产生的,而这里的抽象工厂模式则是针对多个产品等级结构的.当然,单一的产品等级结构也同样适用于抽象工厂模式的.下面为其具体的等级结构图说明: 从上面的结构示意图,可以看到抽象工厂模式中涉及到了多个等级结构的产品角色:同时,针对每一种产品等级结构,都有一种专门的工厂角色负责创建对应的产品,这