Loading... # 设计模式(六)——工厂方法模式 ## 参考 > 大话设计模式  ——  程杰 著 ## 目录 [设计模式(一)——简单工厂模式](https://www.princelei.club/archives/67.html) [设计模式(二)——策略模式](https://www.princelei.club/archives/68.html) [设计模式(三)——设计原则](https://www.princelei.club/archives/116.html) [设计模式(四)——装饰模式](https://www.princelei.club/archives/117.html) [设计模式(五)——代理模式](https://www.princelei.club/archives/119.html) [设计模式(六)——工厂方法模式](https://www.princelei.club/archives/132.html) [设计模式(七)——原型模式](https://www.princelei.club/archives/133.html) [设计模式(八)——模板方法模式](https://www.princelei.club/archives/134.html) [设计模式(九)——外观模式](https://www.princelei.club/archives/135.html) [设计模式(十)——建造者模式](https://www.princelei.club/archives/136.html) [设计模式(十一)——观察者模式](https://www.princelei.club/archives/137.html) [设计模式(十二)——抽象工厂模式](https://www.princelei.club/archives/138.html) [设计模式(十三)——状态模式](https://www.princelei.club/archives/139.html) [设计模式(十四)——适配器模式](https://www.princelei.club/archives/140.html) [设计模式(十五)——备忘录模式](https://www.princelei.club/archives/141.html) [设计模式(十六)——组合模式](https://www.princelei.club/archives/147.html) [设计模式(十七)——迭代器模式](https://www.princelei.club/archives/148.html) [设计模式(十八)——单例模式](https://www.princelei.club/archives/157.html) [设计模式(十九)——桥接模式](https://www.princelei.club/archives/159.html) [设计模式(二十)——命令模式](https://www.princelei.club/archives/160.html) [设计模式(二十一)——职责链模式](https://www.princelei.club/archives/161.html) [设计模式(二十二)——中介者模式](https://www.princelei.club/archives/162.html) [设计模式(二十三)——享元模式](https://www.princelei.club/archives/163.html) [设计模式(二十四)——解释器模式](https://www.princelei.club/archives/173.html) [设计模式(二十五)——访问者模式](https://www.princelei.club/archives/174.html) ## 何为工厂方法模式 - 工厂方法模式(Factory Method),定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类实例化延迟到其子类 ## 实现加减乘除计算程序 - 简单工厂模式实现 ``` /** * 工厂接口 */ public interface IFactory { Operation getOper(String type); } ``` ``` /** * 计算接口 */ public interface Operation { double getResult(); void setNumberA(double numberA); void setNumberB(double numberB); } ``` ``` /** * 加法类 */ public class OperationAdd implements Operation { private double numberA; private double numberB; @Override public double getResult() { return numberA + numberB; } @Override public void setNumberA(double numberA) { this.numberA = numberA; } @Override public void setNumberB(double numberB) { this.numberB = numberB; } } ``` ``` /** * 减法类 */ public class OperationSub implements Operation { private double numberA; private double numberB; @Override public double getResult() { return numberA - numberB; } @Override public void setNumberA(double numberA) { this.numberA = numberA; } @Override public void setNumberB(double numberB) { this.numberB = numberB; } } ``` ``` /** * 乘法类 */ public class OperationMul implements Operation { private double numberA; private double numberB; @Override public double getResult() { return numberA * numberB; } @Override public void setNumberA(double numberA) { this.numberA = numberA; } @Override public void setNumberB(double numberB) { this.numberB = numberB; } } ``` ``` /** * 除法类 */ public class OperationDiv implements Operation { private double numberA; private double numberB; @Override public double getResult() { if (numberB != 0) { return numberA / numberB; } else { throw new IllegalArgumentException("除数不能为0"); } } @Override public void setNumberA(double numberA) { this.numberA = numberA; } @Override public void setNumberB(double numberB) { this.numberB = numberB; } } ``` ``` /** * 工厂类 */ public class OperationFactory implements IFactory { private Operation oper = null; @Override public Operation getOper(String type) { switch (type) { case "+": oper = new OperationAdd(); break; case "-": oper = new OperationSub(); break; case "*": oper = new OperationMul(); break; case "/": oper = new OperationDiv(); } return oper; } } ``` ``` /** * 客户端 */ public class MainClass { public static void main(String[] args) { Operation oper = new OperationFactory().getOper("+"); oper.setNumberA(1); oper.setNumberB(2); System.out.println(oper.getResult()); } } ``` 简单工厂模式最大的优点在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关类,对于客户端来说,去除了与具体产品的依赖。如果上述程序我要添加一个‘求M数的N次方’的功能,我们是一定要给运算工厂类的方法里加‘case’的分支条件的,修改原有的类,这就等于是说,我们不但对扩展开放了,对修改也开放了,这样就违背了开放-封闭原则。 - 工厂方法模式实现 ``` /** * 工厂接口 */ public interface IFactory { Operation createOperation(); } ``` ``` /** * 计算抽象类 */ public interface Operation { double getResult(); void setNumberA(double numberA); void setNumberB(double numberB); } ``` ``` /** * 加法类 */ public class OperationAdd implements Operation { private double numberA; private double numberB; @Override public double getResult() { return numberA + numberB; } @Override public void setNumberA(double numberA) { this.numberA = numberA; } @Override public void setNumberB(double numberB) { this.numberB = numberB; } } ``` ``` /** * 减法类 */ public class OperationSub implements Operation { private double numberA; private double numberB; @Override public double getResult() { return numberA - numberB; } @Override public void setNumberA(double numberA) { this.numberA = numberA; } @Override public void setNumberB(double numberB) { this.numberB = numberB; } } ``` ``` /** * 乘法类 */ public class OperationMul implements Operation { private double numberA; private double numberB; @Override public double getResult() { return numberA * numberB; } @Override public void setNumberA(double numberA) { this.numberA = numberA; } @Override public void setNumberB(double numberB) { this.numberB = numberB; } } ``` ``` /** * 除法类 */ public class OperationDiv implements Operation { private double numberA; private double numberB; @Override public double getResult() { if (numberB != 0) { return numberA / numberB; } else { throw new IllegalArgumentException("除数不能为0"); } } @Override public void setNumberA(double numberA) { this.numberA = numberA; } @Override public void setNumberB(double numberB) { this.numberB = numberB; } } ``` ``` /** * 加法工厂类 */ public class AddFactory implements IFactory { @Override public Operation createOperation() { return new OperationAdd(); } } ``` ``` /** * 减法工厂类 */ public class SubFactory implements IFactory { @Override public Operation createOperation() { return new OperationSub(); } } ``` ``` /** * 乘法工厂类 */ public class MulFactory implements IFactory { @Override public Operation createOperation() { return new OperationMul(); } } ``` ``` /** * 除法工厂类 */ public class DivFactory implements IFactory{ @Override public Operation createOperation() { return new OperationDiv(); } } ``` ``` /** * 客户端 */ public class FactoryMethodMainClass { public static void main(String[] args) { IFactory operFactory = new DivFactory(); Operation oper = operFactory.createOperation(); oper.setNumberA(1); oper.setNumberB(0); System.out.println(oper.getResult()); } } ``` 当需要添加功能时,我们需要添加一个功能类,一个工厂类,并修改客户端调用的具体工厂。 工厂方法模式实现时,客户端需要决定实例化哪一个工厂来实现运算类,选择判断的问题还是存在的,也就是说,工厂方法把简单工厂内部逻辑判断移到了客户端代码来进行,你想要的加功能,本来是改工厂类,而现在是修改客户端。 工厂方法克服了简单工厂违背开放-封闭原则的缺点,又保持了封装对象创建过程的优点。工厂方法模式是简单工厂模式的进一步抽象和推广。由于使用了多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点。但缺点是由于每加一个产品,就需要加一个产品工厂的类,增加了额外的开发量。 Last modification:June 11th, 2020 at 06:26 pm © 允许规范转载