1. 模式简介
简单工厂模式(Simple Factory Pattern):它属于创建型设计模式
,不属于23种设计模式
。在简单工厂模式中,可以根据参数的不同返回不同类的实例。简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。本文将使用 糖果工厂生产不同口味的糖果 这个实际场景,用代码来实现 简单工厂模式。
2. 模式角色
简单工厂包含3个角色:
- 工厂角色(
CandyFactory
):主要负责创建具体的实例。 - 抽象实体(
Candy
):它是工厂角色所创建的所有实例的父类,包含所有具体实例所共有的公共接口。 - 具体特征的实体(
LemonCandy
和 WatermelonCandy
):所有由工厂角色创建出来的实例都属于具体实体。
3. UML图例
3.1. 未使用简单工厂模式的UML图
3.2. 使用简单工厂模式之后的UML图
4. 代码实现
4.1. 步骤一:创建抽象糖果类
Candy.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
public abstract class Candy {
public abstract void taste(); }
|
4.2. 步骤二:创建具体的不同口味的糖果类
LemonCandy.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
public class LemonCandy extends Candy {
@Override public void taste() { System.out.println("柠檬味"); } }
|
WatermelonCandy.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
public class WatermelonCandy extends Candy {
@Override public void taste() { System.out.println("西瓜味"); } }
|
4.3. 步骤三:创建糖果工厂
CandyFactory.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
|
public class CandyFactory {
public Candy produceCandy(String taste) { if ("lemon".equalsIgnoreCase(taste)) { return new LemonCandy(); } else if ("watermelon".equalsIgnoreCase(taste)) { return new WatermelonCandy(); } return null; }
public Candy produceCandy(Class c) { Candy candy = null; try { candy = (Candy) Class.forName(c.getSimpleName()).newInstance(); } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) { e.printStackTrace(); } return candy; } }
|
4.4. 步骤四:调用工厂类生产具体口味的糖果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| import com.xkcoding.design.pattern.creational.simplefactory.Candy; import com.xkcoding.design.pattern.creational.simplefactory.CandyFactory; import com.xkcoding.design.pattern.creational.simplefactory.LemonCandy; import com.xkcoding.design.pattern.creational.simplefactory.WatermelonCandy;
public class PatternTest { public static void main(String[] args) { CandyFactory factory = new CandyFactory(); Candy candy1 = factory.produceCandy("lemon"); candy1.taste(); Candy candy2 = factory.produceCandy("watermelon"); candy2.taste();
Candy candy3 = factory.produceCandy(LemonCandy.class); candy3.taste(); Candy candy4 = factory.produceCandy(WatermelonCandy.class); candy4.taste(); } }
|
5. 应用
6. 场景
- 工厂类负责创建的对象比较少:由于创建的对象较少,不会造成工厂方法中的业务逻辑太过复杂。
- 客户端只知道传入工厂类的参数,对于如何创建对象不关心:客户端既不需要关心创建细节,甚至连类名都不需要记住,只需要知道类型所对应的参数。
7. 优缺点
优点: 以本例为例,1、糖果调用方想创建一个具体口味的糖果对象,只要知道其口味就可以。 2、扩展性高,如果想增加一个具体口味的糖果,只要在工厂类中添加一种生产逻辑就可以实现。 3、屏蔽糖果的具体实现,调用方只关心抽象实体的通用接口在具体口味糖果类中的不同实现。
缺点: 以本例为例,每增加一种糖果口味,都需要增加一种具体的实现类,同时在工厂类中添加对应的生产逻辑,如果系统中存在很多不同口味的糖果,则会导致类的数量成倍增加,增加了系统的复杂度,同时增加类之间的依赖。
8. 完整代码地址
https://github.com/xkcoding/design-pattern/tree/master/src/main/java/com/xkcoding/design/pattern/creational/simplefactory