简单工厂和工厂方法应该是我们在开发中应用的比较多的设计模式之一了,今天我们聊聊这两个工厂,对比一下这两个工厂各自的优缺点
简单工厂模式
角色组成:
工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑,根据逻辑不同,产生具体的工厂产品
抽象产品角色:它一般是具体产品继承的父类或者实现的接口。由接口或者抽象类来实现。
结构图如下:
我们用简单工厂实现四则运算
代码如下:具有某一类共有特性操作 我们提出出来的抽象类
package simple;
public abstract class Operation {
public double number1 = 0.0;
public double number2 = 0.0;
//计算方法 具体运算由子类去实现
public abstract double operate();
}
具体实现类((以下是Operation抽象类四则运算的的具体实现)
package simple;
public class AddOperation extends Operation {
@Override
public double operate() {
return super.number1 + super.number2;
}
}
package simple;
public class DuctOperation extends Operation {
@Override
public double operate() {
return super.number1 - super.number2;
}
}
package simple;
public class MulOperation extends Operation {
@Override
public double operate() {
return super.number1 * super.number2;
}
}
package simple;
public class SuxOperation extends Operation {
@Override
public double operate() {
return super.number1 / super.number2;
}
}
现在我们引出工厂方法 专门为我们创建出对应的对象
package simple;
import org.junit.Test;
public class SimPleFactory {
public static Operation createOperation(String type) {
Operation oper = null;
switch (type) {
case "+":
oper = new AddOperation();
break;
case "-":
oper = new DuctOperation();
break;
case "*":
oper = new MulOperation();
break;
case "/":
oper = new SuxOperation();
break;
}
return oper;
}
}
上图可见 我们是根据外界传进来的type来确定创建什么样的对象 SimPleFactory 主要负责Operation 对象的创建
测试:
Operation operation = SimPleFactory.createOperation("+");
operation.number1 = 10;
operation.number2 = 3;
System.out.println(operation.operate());
输出结果为13.0
上面就是我们的简单工厂方法的具体案列 我们来想一想 想一想 假如我们要新的运算法则 比如新加一个平方根计算的法则
我们改怎么修改呢?我们是不是要在SimPleFactory 这个类中的switch中加上case“平方根” 还要创建对应的类去实现Operation 来 完成平方根的操作 这样我们不仅仅对Operation开放了 而且对 SimPleFactory的修改也开放了 这里违背了开放-封闭原则。
同样我们来使用工厂方法来实现上面的功能
工厂方法模式
定义一个创建对象的接口 让子类去决定实例化哪一个类,工厂方法使对象的创建延迟到了子类
抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。
具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。在java中它由具体的类来实现。
抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。
具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现
结构图如下:
我们该如何优化上面的运算法则呢 是否可以更好的实现添加新的运算而不导致我么违背对应设计原则呢
首先我们来构建运算对象的工厂方法
package method;
public interface OperateFactory {
//创建对应操作的对象
public Operation createOperate();
}
下面是工厂类的具体实现着(真正的对象的创建延迟到子类中) 当然下面是4个类哦
package method;
//加法工厂类 创建加法操作类
public class AddFactory implements OperateFactory {
@Override
public AddOperation createOperate() {
return new AddOperation();
}
}
package method;
//减法工厂类 创建减法操作类
public class DuctFactory implements OperateFactory {
@Override
public Operation createOperate() {
return new DuctOperation();
}
}
package method;
//乘法工厂类 创建乘法操作类
public class MulFactory implements OperateFactory {
@Override
public Operation createOperate() {
return new MulOperation();
}
}
下面还是和简单工厂一样 需要提供抽象的运算和具体的运算实现
抽象的运算
package method;
public abstract class Operation {
public double number1 = 0.0;
public double number2 = 0.0;
//计算方法
public abstract double operate();
}
四则运算的实现
package method;
public class AddOperation extends Operation {
@Override
public double operate() {
return super.number1 + super.number2;
}
}
package method;
public class DuctOperation extends Operation {
@Override
public double operate() {
return super.number1 - super.number2;
}
}
package method;
public class MulOperation extends Operation {
@Override
public double operate() {
return super.number1 * super.number2;
}
}
上面就是工厂方法改造之后的对象 我们将简单工厂case决定对象的创建有实际的对象工厂来替换了 测试如下:
package method;
import org.junit.Test;
public class test {
@Test
public void testAdd(){
OperateFactory factory=new AddFactory();
Operation operation=factory.createOperate();
operation.number1=10;
operation.number2=3;
System.out.println(operation.operate());
}
}
//结果13.0
显然我们如果增加对应的运算(平方根运算) 我们只需要该 OperateFactory factory=new “对象的Factory” 也就是我们只需要去扩展Operation的平方根的实现 和 创建OperateFactory 平方根运算类实现 我们只是在原有基础上拓展 而不是修改!
当然 这里还是有不足支持 每增加一处 我们就需要添加很多额外的工作量,还有没有更好的设计方法呢?
必须有 就是我们前面装饰模式提到的反射,这个我们后续了解。