简单工厂模式

173 阅读3分钟

简述

工厂模式是最常见的一类创建型设计模式。通常说的工厂模式是指工厂方法模式。这里讲的简单工厂模式是工厂方法模式的“小弟”,它不属于GoF 23种设计模式,但是使用比较频繁,

简单工厂模式定义: 定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。

UML类图

image.png

  • Factory: 工厂类,它是简单工厂模式的核心,负责实现创建所有产品实例;工厂类可以被外界直接调用,创建所需的产品对象
  • Product: 抽象产品类,他是工厂类创建的所有对象的父类,封装了各种产品的公共方法,他的引入提高了系统的灵活性
  • ConcreteProduct: 具体产品角色,它是简单工厂模式的创建目标。

要点

  • 所有的具体产品类都继承于Product类
  • 工厂类中提供了静态的工厂方法,用来创建Product
  • 工厂类中必须传入参数,来决定创建哪个具体的产品

案例

在IM开发过程中,因为引入了不同账号体系的概念,所以需要根据不同的账号类型创建不同的账号信息。

简单工厂模式实现过程如下:

  1. 定义账号产品父类
public Abstract class AcctBase {
    ……
    // 不同的账号体系加密方式不一样
    public Abstract void getEncryPwd();
    ……
}
  1. 定义具体的子类
//IM 账号
public class IMAcct Extends AcctBase{
    ……
    public String getEncryPwd() {
        //IM账号的加密处理
    }
    ……
}

//XX 体系账号
public class XXAcct Extends AcctBase{
    ……
    public String getEncryPwd() {
        //XX账号的加密处理
    }
    ……
}
  1. 定义账号类型,用于工厂方法的参数
Interface AcctType {
    int ACCT_TYPE_IM = 0;
    int ACCT_TYPE_XX = 1;
}
  1. 创建工厂类
public class AcctFactory {
    public static AcctBase createAcct(int acctType) {
        AcctBase acct = null;
        switch (acctType) {
            case AcctType.ACCT_TYPE_IM:
                acct = new IMAcct();
                break;
            case AcctType.ACCT_TYPE_XX:
                acct = new XXAcct();
                break;
            default:
                break;
        }
        return acct;
    }
}

main程序中的使用代码就应该如下:

class Client {
    public static void main(String args[]) {
        AcctBase acct = AcctFactory.createAcct(AcctType.ACCT_TYPE_IM);
        String encryedPwd = acct.getEncryPwd();
        System.out("encryedPwd = " + encryedPwd);
    }
}

大家可以想象上面如果不用简单工厂模式,所有的实现都在一个Acct类中通过if-else处理完成, 后面再添加多个账号类型,可想而知Acct类会非常臃肿庞大,极难维护。

创建对象

与一个对象相关的职责通常有3类: 对象本身的职责,创建对象,使用对象。

对象本身的职责就是对象自身所具有的一些数据和行为。

在Jave中,通常有以下几种创建对象的方式:

  1. 使用new 关键字直接创建对象
  2. 通过反射机制创建对象
  3. 通过clone方法创建对象 (属于原型模式)
  4. 通过工厂类创建。

这里有一点要注意,一个类中不能存在既创建对象,又使用对象的情况,这违背单一职责原则。

总结

优点:

  • 简单工厂模式实现了对象创建和使用的分离
  • 客户端不需要知道具体的创建细节,只需要知道具体产品类对应的参数即可,减少了一些类的记忆。

缺点:

  • 由于工厂类集中了所有产品的创建逻辑,职责过重,一旦不能工作,整个系统都会受到影响
  • 使用简单工厂模式肯定会增加系统类的个数,增加系统的复杂性和理解难度
  • 系统扩展困难,每次新增产品类,都会涉及到工厂类的修改,违背开闭原则
  • 因为工厂类使用的是静态工厂方法,造成工厂角色无法形成基于继承的等级结构

适用场景

  • 工厂类负责创建的对象较少,因为对象不多,所以工厂业务不会太复杂
  • 客户端只知道传入工厂类的参数,对于如何创建对象并不关心