设计模式之简单工厂

简单工厂(Simple Factory)

先看问题(form 《大话设计模式》):

业务场景,需要实现一个计算器,能够简单的实现加、减、乘、除

首先,按照正常的代码来写:

//定义工具类:
public class OperationUtils {

    public static double getResult(String operation, double op1, double op2) {
        switch (operation) {
            case "+":
                return op1 + op2;
            case "-":
                return op1 - op2;
            case "x":
                return op1 * op2;
            case "/":
                return op1 / op2;
            default:
                throw new UnsupportedOperationException("不支持的操作符");
        }
    }
}
//使用
public class Main {
    public static void main(String[] args) {
        double op1=7;
        double op2=9;
        double result= OperationUtils.getResult("+",op1,op2);
    }
}

分析代码:

  • 上面的代码完成了基本的可复用功能,虽然符合单一职责,但是并没有面向对象思想
  • 上面的要求是完成一个计算器,也就是主要业务逻辑便是计算器,进行需求分析我们可以发现,这个计算器功能肯定是会被扩展的,但是在扩展的时候,我们就必须修改原本的代码
  • 原本的核心逻辑被完全裸露出来,这样在修改代码的时候,更加容易引起致命的bug

首先,我们明白上面的代码是不符合面向对象原则的,因为计算类作为核心的业务类,我们却直接将每个逻辑都放在了一个类中,这样带来的问题可能就在扩展功能的时候,很可能就不小心修改了原本的代码,导致新的bug,并且随着功能的完善,比如添加日志等,这个类会越来越臃肿:

因此我们可以使用面向对象将各个功能模块封装起来:

定义操作符接口


public abstract class Operation { double op1; double op2; public Operation(double op1, double op2) { this.op1 = op1; this.op2 = op2; } public abstract double getResult(); }

定义具体的子类

//定义加法操作
public class AddOperation extends Operation {

    @Override
    public double getResult() {
        return op1+op2;
    }

    public AddOperation(double op1,double op2){
        super(op1,op2);
    }
}
//定义减法操作
public class SubOperation extends Operation{

    @Override
    public double getResult() {
        return op1-op2;
    }

    public SubOperation(double op1,double op2){
        super(op1,op2);
    }
}
//乘法
//除法
//...

定义操作符工厂类


public class OperationFactory { public static Operation getOperation(String operation, double op1, double op2) { switch (operation) { case "+": return new AddOperation(op1, op2); case "-": return new SubOperation(op1, op2); case "*": return new MulOperation(op1, op2); case "/": return new DivOperation(op1, op2); default: throw new UnsupportedOperationException("不支持的操作"); } } }

使用方式如下

public class Main {
    public static void main(String[] args) {
        double op1=7;
        double op2=9;
        Operation operation= OperationFactory.getOperation("+",op1,op2);
        double result = operation.getResult();
    }
}

示例代码均在:https://github.com/dengchengchao/design-pattern

可以看到,经过使用面向对象封装了以后,各个类的职责便分离开来Factory就负责根据传入的参数产生不同的类,而其他Operation则负责完成相关的工作。

但是这样的缺点便是产生生了许多的小类,编码工作量提升了不少,但是在面对以后的扩展和修改的时候需求的时候,利是大于弊的。

这便是简单工厂。

定义

  • 简单工厂模式又叫静态方法模式,它属于类创建型模式

  • 它能将创建对象对象本身的职责分割开来

  • 不属于23种设计模式之一

简单工厂解决了什么问题?

前面说过,简单工厂属于类创建型模式,而它的功能是将创建对象对象本身的职责分开。

当在类的设计过程中,如果类的行为依赖于用户的输入而定,那么这个类可能会同时担任根据输入选择具体行为的职责,那么在扩展/更新这个类的时候,就很可能不小心修改原本正确的代码。并且还可能随着类的扩展,类越来越雍容。

此时简单工厂就能很好的解决这个问题。

模式结构

image

其中:

  • Client:通过Factory获取相关对象,并使用相关对象

  • Product:作为抽象产品类,将具体的产品类公共代码封装,使其他具体产品继承该类

  • Factory: 工厂类,负责根据相关的规则产生出相应的对象
  • ConcreteProduct:具体产品类,继承于Product

模式优缺点

  • 简单工厂只是简单的将功能使用面向对象封装起来,但是它依然违背了开闭原则,只是使用简单工厂因为将对象的创造和使用分离开来,降低了出错率。

  • 使用简单工厂会带来许多的小类,导致代码比较多

  • 但是简单工厂能够将对象的创建和使用分开,并且封装了功能代码,增加了容错率

尊重劳动成果,转载注明出处

参考文章:
《大话设计模式》
《Head First 设计模式》
简单工厂–张玉莹的个人博客
设计模式01之 简单工厂模式(创建模式)