简述
简单工厂模式属于创建类模式(主要关注怎样创建对象,特点是将对象的创建和使用分离),是工厂模式中的一种,而工厂模式又可以分为简单工厂模式、工厂方法模式、抽象工厂模式。
简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例,简单工厂模式是工厂模式中最简单使用的一种模式。
工厂模式的定义:定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中。这满足创建型模式中所要求的“创建与使用相分离”的特点
介绍
我们把被创建的对象称为“产品”,把创建产品的对象称为“工厂”。如果要创建的产品不多,只要一个工厂类就可以完成,这种模式叫“简单工厂模式”。
简单来说,简单工厂模式有一个具体的工厂类,这个工厂类可以生产多个不同的产品,属于创建型设计模式(简单工厂模式不在 GoF 23 种设计模式之列)。在简单工厂模式中创建实例的方法通常为静态方法,所以简单工厂模式又可以叫静态工厂方法模式
简单工厂模式每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度,违背了“开闭原则”。
注:工厂方法模式满足开闭原则,简单工厂模式不满足开闭原则,工厂方法模式是对简单工厂模式的进一步抽象化,它的好处就是等新增产品时不需要修改原来的代码就可以进行扩展,也就是新增新产品不影响原来的产品。
应用场景
在日常开发中,凡是需要生成复杂对象的地方,都可以尝试考虑使用工厂模式来代替。复杂对象指的是类的构造函数参数过多等对类的构造有影响的情况,因为类的构造过于复杂,如果直接在其他业务类内使用,则两者的耦合过重,后续业务更改,就需要在任何引用该类的源代码内进行更改,修改对应的所有依赖就很浪费时间了,也就是不符合设计模式的开闭原则,开闭原则要求一个软件实体(模块、接口、类、方法等)对扩展开放,对修改关闭。
简单工厂模式的优点:
- 工厂类包含逻辑判断,可以决定在什么时候创建哪一个产品的实例。客户端(调用者)可以免除直接创建产品对象的职责,很方便的创建出相应的产品。工厂和产品的职责区分明确。
- 客户端无需知道所创建具体产品的类名,只需知道对应参数即可。
- 也可以引入配置文件(xml),在不修改客户端代码的情况下更换和添加新的具体产品类。
简单工厂模式的缺点:
- 简单工厂模式的工厂类单一,也就是一个工厂负责所有产品的创建,职责过重,一旦出现异常,整个工厂将受影响。并工厂类代码会非常臃肿,违背高聚合原则。
- 使用简单工厂模式会增加系统中类的个数(引入新的工厂类),增加系统的复杂度和理解难度
- 扩展困难,一旦增加新产品不得不修改工厂逻辑,在产品类型较多时,可能造成逻辑过于复杂,违反开闭原则。
- 简单工厂模式使用了 static 工厂方法,造成工厂角色无法形成基于继承的等级结构。
总结
对于产品种类相对较少的情况,可以考虑使用简单工厂模式。使用简单工厂模式的客户端只需要传入工厂类的参数,而不需要关心如何创建对象的逻辑,具体产品类的名称是对客户端是屏蔽的。严格上来说,简单工厂模式不算是设计模式。
模式的结构与实现
简单工厂模式的主要角色如下:
- 简单工厂(SimpleFactory):是简单工厂模式的核心,负责实现创建所有实例的内部逻辑。工厂类的创建产品类的方法可以被外界直接调用,创建所需的产品对象。
- 抽象产品(AbstractProduct):是简单工厂创建的所有对象的父类,负责描述所有实例共有的公共接口。
- 具体产品(SpecificProduct1、SpecificProduct):简单工厂模式的创建目标(对象)。
uml类图
代码示例:
package com.tianye.designModel;
/**
* @author 田野上的风筝
* @version V1.0
* @Description: 简单工厂
* @date 2020/12/3 15:17
*/
public class SimpleFactoryDemo {
public static void main(String[] args) {
Animal cow = LivestockFarmFactory.production(LivestockFarmFactory.COW);
cow.growUp();
Animal sheep = LivestockFarmFactory.production(LivestockFarmFactory.SHEEP);
sheep.growUp();
}
}
//抽象产品 动物
abstract class Animal{
abstract void growUp();
}
//简单工厂
class LivestockFarmFactory{
static final String COW = "cow";
static final String SHEEP = "sheep";
//
public static Animal production(String s){
switch (s){
case COW:
return new Cow();
case SHEEP:
return new Sheep();
}
return null;
}
// public static Animal productionCow(){
// return new Cow();
// }
// public static Animal productionSheep(){
// return new Sheep();
// }
}
//具体产品 牛
class Cow extends Animal{
@Override
public void growUp() {
System.out.println("生产牛,牛在成长");
}
}
//具体产品 羊
class Sheep extends Animal{
@Override
public void growUp() {
System.out.println("生产羊,羊在成长");
}
}
//添加新的需求,还需要添加新的产品具体类,并修改工厂逻辑,不符合开闭原则
class OtherAnimal extends Animal{
@Override
public void growUp() {
System.out.println("生产其他动物,其他动物在成长");
}
}
运行mian方法,效果