设计模式速记-工厂模式与抽象工厂模式
一、工厂模式概述
1. 什么是工厂模式
工厂模式定义:
定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中。这满足创建型模式中所要求的“创建与使用相分离”的特点。
工厂模式是一种创建型模式,根据创建的产品是具体产品还是工厂可以将工厂模式分为简单工厂模式和工厂方法模式;
因为简单工厂模式创建产品时会违反开闭原则,所以简单工厂模式不属于GoF的23种设计模式。(开闭原则:如若创建新产品不可改变现有代码)
2. 工厂模式的使用场景
工厂模式的使用场景一般在于创建复杂对象的时候,比如要创建一个配置类Properties,每次创建都可能都要配置很多“属性-值”对,所以可以通过工厂模式来对创建方法进行封装。
简单工厂模式和工厂方法模式的区别在于,简单工厂模式仅用一个工厂就能完成对象创建任务;而工厂方法模式是通过创建具体工厂再通过具体工厂来创建对象,这样就避免了简单工厂模式需要违反开闭原则才能添加新功能的问题。例如
- 简单工厂模式例子:
- 创建具体工厂类MoneyFactory
- 通过MoneyFactory的具体方法来获取美元/人民币
- 工厂方法模式例子:
- 创建抽象工厂接口
- 抽象工厂类派生人民币具体工厂和美元具体工厂
- 通过美元具体工厂创建美元对象,通过人民币具体工厂创建人民币对象
通过上述例子可知,工厂方法模式与简单工厂模式的区别在于工厂方法模式是通过创建具体工厂来生产对象,而简单工厂模式是直接创建对象,所以简单工厂模式违反了开闭原则;而工厂方法模式添加新产品的时候可以通过增加新工厂来创建新对象,故而工厂方法模式为GoF的23中设计模式之一。
3. 抽象工厂模式
抽象工厂模式即是工厂模式的升级版,在工厂模式中工厂只能生产一种产品,比如电子厂只能生产电路板;但现实中电子厂可能还会生产电子器件,所以此时就可以使用抽象工厂模式。
4. 工厂模式与抽象工厂模式的区别
- 工厂方法模式
- 一个抽象产品类,可以派生出多个具体产品类。
- 一个抽象工厂类,可以派生出多个具体工厂类。
- 每个具体工厂类只能创建一个具体产品类的实例。
- 抽象工厂模式
- 多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。
- 一个抽象工厂类,可以派生出多个具体工厂类。
- 每个具体工厂类可以创建多个具体产品类的实例。
所以工厂模式与抽象工厂模式的主要区别在于:
- 工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。
- 工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。
二、示例
就上述创建钱币的示例分别对简单工厂模式和工厂方法模式举例:
1. 简单工厂模式
-
钱币接口
/** * @Description 钱币接口,钱币具体类需实现此接口 */ public interface Money { /** * 获取钱币类别 * @return RMB or dollar */ String getType(); /** * 获取面值 * @return 钱币面值 */ int getValue(); }
-
人民币和美元具体类
/** * @Description 人民币产品类 */ public class RMBMoney implements Money { /** * 人民币面值 */ private int value; public RMBMoney(int value) { this.value = value; } @Override public String getType() { return "RMB"; } @Override public int getValue() { return this.value; } } /** * @Description 美元产品类 */ public class DollarMoney implements Money { /** * 美元面值 */ private int value; public DollarMoney(int value) { this.value = value; } @Override public String getType() { return "dollar"; } @Override public int getValue() { return this.value; } }
-
钱币工厂类
/** * @Description 钱币工厂,生产美元/人民币 */ public class MoneyFactory { /** * 生产美元/钱币 的工厂方法 * @param type 钱币类型 * @param value 钱币面值 * @return 钱币具体对象 */ public static Money makingMoney(String type,int value){ if(type != null && "RMB