参考程杰《大话设计模式》
工厂模式:为创建对象提供过度接口,以便将创建对象的具体过程隐藏起来。
(1)简单工厂模式Simple Factory:不利于产生系列产品;
(2)工厂方法模式Factory Method:又称为多形性工厂;
(3)抽象工厂模式Abstract Factory:又称为工具箱,产生产品族,但不利于产生新的产品;
三种工厂模式逐步抽象。GoF中工厂模式只分为两类,工厂方法和抽象工厂,认为简单工厂是工厂方法的一种特例而已。
简单工厂模式
使用工厂创建不同的对象
当需要增加一个Operation时,需要先增加一个继承自Operation的子类,然后在工厂的switch里增加新的分支。
实例
定义枚举类型,作为工厂里switch的类型
public enum OperationTypeEnum {
ADD(0),
SUB(1),
MUL(2),
DIV(3)
;
private Integer code;
OperationTypeEnum(Integer code) {
this.code = code;
}
}
创建操作的基类,和其子类,子类实现自己的相关逻辑
public abstract class Operation {
protected double numA;
protected double numB;
public abstract double getResult() throws Exception;
public Operation(double numA, double numB) {
this.numA = numA;
this.numB = numB;
}
public void setNumA(double numA) {
this.numA = numA;
}
public void setNumB(double numB) {
this.numB = numB;
}
public Operation() {
}
}
public class OperationAdd extends Operation{
@Override
public double getResult() {
return numA + numB;
}
}
public class OperationSub extends Operation{
@Override
public double getResult() {
return numA - numB;
}
}
public class OperationMul extends Operation {
@Override
public double getResult() {
return numA * numB;
}
}
public class OperationDiv extends Operation {
final double exp = 0.00001d;
@Override
public double getResult() throws Exception {
if(Math.abs(numB - 0d) < exp){
throw new Exception("除数不能为0");
}
return numA / numB;
}
}
工厂类,根据不同枚举,生产不同子类
public class SimpleFactory {
public static Operation creatOperation(OperationTypeEnum type){
switch (type){
case ADD:
return new OperationAdd();
case SUB:
return new OperationSub();
case MUL:
return new OperationMul();
case DIV:
return new OperationDiv();
default:
return null;
}
}
}
使用
public class TestdemoApplication {
public static void main(String[] args) {
double numA = 100.954d;
double numB = 21.2d;
Operation operation = SimpleFactory.creatOperation(OperationTypeEnum.ADD);
operation.setNumA(numA);
operation.setNumB(numB);
System.out.println(operation.getResult());
operation = SimpleFactory.creatOperation(OperationTypeEnum.SUB);
operation.setNumA(numA);
operation.setNumB(numB);
System.out.println(operation.getResult());
operation = SimpleFactory.creatOperation(OperationTypeEnum.MUL);
operation.setNumA(numA);
operation.setNumB(numB);
System.out.println(operation.getResult());
operation = SimpleFactory.creatOperation(OperationTypeEnum.DIV);
operation.setNumA(numA);
operation.setNumB(numB);
System.out.println(operation.getResult());
}
}
输出结果
工厂方法模式
定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
当需要增加一个Operation时,不需要修改已有代码,只需要先增加一个继承自Operation的子类,再新增一个工厂子类,用来生产新的Operation子类。
实例
工厂接口和其子类,即具体生成不同产品的子工厂
public interface Factory {
Operation createOperation();
}
public class AddFactory implements Factory {
@Override
public Operation createOperation() {
return new OperationAdd();
}
}
public class SubFactory implements Factory {
@Override
public Operation createOperation() {
return new OperationSub();
}
}
public class MulFactory implements Factory {
@Override
public Operation createOperation() {
return new OperationMul();
}
}
public class DivFactory implements Factory {
@Override
public Operation createOperation() {
return new OperationDiv();
}
}
创建操作的基类,和其子类,子类实现自己的相关逻辑
public abstract class Operation {
protected double numA;
protected double numB;
public abstract double getResult() throws Exception;
public Operation(double numA, double numB) {
this.numA = numA;
this.numB = numB;
}
public void setNumA(double numA) {
this.numA = numA;
}
public void setNumB(double numB) {
this.numB = numB;
}
public Operation() {
}
}
public class OperationAdd extends Operation{
@Override
public double getResult() {
return numA + numB;
}
}
public class OperationSub extends Operation{
@Override
public double getResult() {
return numA - numB;
}
}
public class OperationMul extends Operation {
@Override
public double getResult() {
return numA * numB;
}
}
public class OperationDiv extends Operation {
final double exp = 0.00001d;
@Override
public double getResult() throws Exception {
if(Math.abs(numB - 0d) < exp){
throw new Exception("除数不能为0");
}
return numA / numB;
}
}
使用
```java
public class TestdemoApplication {
public static void main(String[] args) {
double numA = 100.954d;
double numB = 21.2d;
//先创建工厂
Factory factory = new AddFactory();
Operation operation = factory.createOperation();
operation.setNumA(numA);
operation.setNumB(numB);
System.out.println(operation.getResult());
factory = new SubFactory();
operation = factory.createOperation();
operation.setNumA(numA);
operation.setNumB(numB);
System.out.println(operation.getResult());
factory = new MulFactory();
operation = factory.createOperation();
operation.setNumA(numA);
operation.setNumB(numB);
System.out.println(operation.getResult());
factory = new DivFactory();
operation = factory.createOperation();
operation.setNumA(numA);
operation.setNumB(numB);
System.out.println(operation.getResult());
}
}
输出结果
抽象工厂模式
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
如果要新增一个产品,需要新增的类很多,如下实例中,需要新增产品的抽象类(ProductComputer),新增其实现类(AppleProductComputer,MiProductComputer),修改工厂类(Factory,AppleFactory,MiFactory新增createPadComputer()方法)
实例
工厂相关接口和实现类
public interface Factory {
ProductPhone createPhone();
ProductPad createPad();
}
//生成苹果产品的工厂
public class AppleFactory implements Factory{
@Override
public ProductPhone createPhone() {
return new AppleProductPhone();
}
@Override
public ProductPad createPad() {
return new AppleProductPad();
}
}
//生成小米产品的工厂
public class MiFactory implements Factory{
@Override
public ProductPhone createPhone() {
return new MiProductPhone();
}
@Override
public ProductPad createPad() {
return new MiProductPad();
}
}
产品相关接口和实现类
//产品--手机
public interface ProductPhone {
void installScreen();
void installkeyboard();
}
public class AppleProductPhone implements ProductPhone{
@Override
public void installScreen() {
System.out.println("安装苹果手机屏幕");
}
@Override
public void installkeyboard() {
System.out.println("安装苹果手机键盘");
}
}
public class MiProductPhone implements ProductPhone{
@Override
public void installScreen() {
System.out.println("安装小米手机屏幕");
}
@Override
public void installkeyboard() {
System.out.println("安装小米手机键盘");
}
}
//产品--平板
public interface ProductPad {
void installScreen();
void installkeyboard();
}
public class AppleProductPad implements ProductPad{
@Override
public void installScreen() {
System.out.println("安装苹果平板屏幕");
}
@Override
public void installkeyboard() {
System.out.println("安装苹果平板键盘");
}
}
public class MiProductPad implements ProductPad{
@Override
public void installScreen() {
System.out.println("安装小米平板屏幕");
}
@Override
public void installkeyboard() {
System.out.println("安装小米平板键盘");
}
}
使用
public class TestdemoApplication {
public static void main(String[] args) {
Factory factory = new MiFactory();
ProductPhone phone = factory.createPhone();
ProductPad pad = factory.createPad();
phone.installkeyboard();
phone.installScreen();
pad.installkeyboard();
pad.installScreen();
}
}
输出结果
总结
- 简单工厂模式最大优点在于工厂类中包含了必要的逻辑判断,根据客户的选择条件动态实例化相关类,对于客户端来说,去除了与具体产品的依赖
- 工厂方法模式,客户端需要决定实例化哪一个工厂来实现运算类,选择判断的问题还存在,但是判断是在客户端做的。
- 抽象工厂模式最大好处是便于交换产品系列,具体的工厂在初始化时改变,即可改变不同的产品配置。并且具体的创建实例过程与客户端分离,客户端只是通过它们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户代码中。
- 所有在用简单工厂的地方,都可以考虑用反射+配置文件方式去除switch或if分支,解除分支判断带来的耦合。