• 设计模式—简单工厂


    目录

    一、前言

    二、简单工厂模式

    1、计算器例子

    2、优化后版本

    3、结合面向对象进行优化(封装)

    3.1、Operation运算类

    3.2、客户端

    4、利用面向对象三大特性(继承和多态)

    4.1、Operation类

    4.2、加法类

    4.3、减法类

    4.4、乘法类

    4.5、除法类

    4.6、简单工厂

    4.7、客户端

    5、简单工厂模式优点

    6、简单工厂模式缺点

    三、总结


    一、前言

    简单工厂模式不属于GoF23种设计模式之一,但是实际中用途广泛,并且可以作为学习“工厂方法模式”以及“抽象工厂模式”的基础。在简单工厂模式中,工厂类提供一个创建产品的工厂方法,用于创建各种产品。客户端只需传入对应的参数,利用该方法即可根据传入参数的不同返回不同的具体产品对象。

    二、简单工厂模式

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

    因为在简单工厂模式用于创建实例的方法是静态的方法,因此简单工厂模式又被称为静态工厂方法模式,它属于类创建型模式。

    在介绍简单工厂之前先来看一个简单的计算器小栗子。

    1、计算器例子

    1. public static void main(String[] args) {
    2. Scanner scanner = new Scanner(System.in);
    3. System.out.println("请输入数字A:");
    4. String A = scanner.nextLine();
    5. System.out.println("请选择运算符号(+、-、*、/):");
    6. String B = scanner.nextLine();
    7. System.out.println("请输入数字B:");
    8. String C = scanner.nextLine();
    9. String D = "";
    10. if(B == "+"){
    11. D = String.valueOf(Double.parseDouble(A) + Double.parseDouble(C));
    12. }
    13. if(B == "-"){
    14. D = String.valueOf(Double.parseDouble(A) - Double.parseDouble(C));
    15. }
    16. if(B == "*"){
    17. D = String.valueOf(Double.parseDouble(A) * Double.parseDouble(C));
    18. }
    19. if(B == "/"){
    20. D = String.valueOf(Double.parseDouble(A) / Double.parseDouble(C));
    21. }
    22. System.out.println("运算结果:"+D);
    23. }

     这段代码存在的问题:

    1. 这样命名是非常不规范的。像A、B、C、D这些,别人扎眼一看肯定不知道这是在做什么。
    2. 判断分支,这样的写法,意味着每个条件都要做判断,等于计算机做了三次无用功。
    3. 如果除数时,客户输入了0怎么办,如果用户输入的是字符符号而不是数字怎么办。

    2、优化后版本

    1. public static void main(String[] args) {
    2. try {
    3. Scanner scanner = new Scanner(System.in);
    4. System.out.println("请输入数字A:");
    5. String numberA = scanner.nextLine();
    6. System.out.println("请选择运算符号(+、-、*、/):");
    7. String operate = scanner.nextLine();
    8. System.out.println("请输入数字B:");
    9. String numberB = scanner.nextLine();
    10. String result = "";
    11. switch (operate ){
    12. case "+":
    13. result = String.valueOf(Double.parseDouble(numberA) + Double.parseDouble(numberB));
    14. break;
    15. case "-":
    16. result = String.valueOf(Double.parseDouble(numberA) - Double.parseDouble(numberB));
    17. break;
    18. case "*":
    19. result = String.valueOf(Double.parseDouble(numberA) * Double.parseDouble(numberB));
    20. break;
    21. case"/":
    22. if (numberB != "0"){
    23. result = String.valueOf(Double.parseDouble(numberA) / Double.parseDouble(numberB));
    24. }else{
    25. result = "除数不能为0";
    26. }
    27. break;
    28. }
    29. System.out.println("运算结果:"+result);
    30. }catch (Exception e){
    31. System.out.println(e);
    32. }
    33. }

    可以看到这一版中优化了变量的命名,将if判断更换成了switch case语句,增加了除数判断是否为0。

    3、结合面向对象进行优化(封装)

    3.1、Operation运算类

    1. public class Operation {
    2. public static String getResult(double numberA, double numberB, String operate){
    3. String result = "";
    4. switch (operate){
    5. case "+":
    6. result = String.valueOf(numberA+ numberB);
    7. break;
    8. case "-":
    9. result = String.valueOf(numberA -numberB);
    10. break;
    11. case "*":
    12. result = String.valueOf(numberA * numberB);
    13. break;
    14. case"/":
    15. if (numberB != 0){
    16. result = String.valueOf(numberA / numberB);
    17. }else{
    18. result = "除数不能为0";
    19. }
    20. break;
    21. }
    22. return result;
    23. }
    24. }

    3.2、客户端

    1. public class Program {
    2. public static void main(String[] args) {
    3. try {
    4. Scanner scanner = new Scanner(System.in);
    5. System.out.println("请输入数字A:");
    6. String numberA = scanner.nextLine();
    7. System.out.println("请选择运算符号(+、-、*、/):");
    8. String operate = scanner.nextLine();
    9. System.out.println("请输入数字B:");
    10. String numberB = scanner.nextLine();
    11. String result = "";
    12. Operation.getResult(Double.parseDouble(numberA), Double.parseDouble(numberB),operate);
    13. System.out.println("运算结果:"+result);
    14. }catch (Exception e){
    15. System.out.println(e);
    16. }
    17. }
    18. }

    4、利用面向对象三大特性(继承和多态)

    4.1、Operation类

    1. public abstract class Operation {
    2. private double numberA;
    3. private double numberB;
    4. public double getNumberA() {
    5. return numberA;
    6. }
    7. public void setNumberA(double numberA) {
    8. this.numberA = numberA;
    9. }
    10. public double getNumberB() {
    11. return numberB;
    12. }
    13. public void setNumberB(double numberB) {
    14. this.numberB = numberB;
    15. }
    16. public abstract double getResult() throws Exception;
    17. }

    4.2、加法类

    1. public class OperationAdd extends Operation{
    2. @Override
    3. public double getResult() {
    4. return getNumberA()+getNumberB();
    5. }
    6. }

    4.3、减法类

    1. public class OperationSub extends Operation{
    2. @Override
    3. public double getResult() {
    4. return getNumberB() - getNumberB();
    5. }
    6. }

    4.4、乘法类

    1. public class OperationMul extends Operation{
    2. @Override
    3. public double getResult() {
    4. return getNumberA() * getNumberB();
    5. }
    6. }

    4.5、除法类

    1. public class OperationDiv extends Operation{
    2. @Override
    3. public double getResult() throws Exception {
    4. if (getNumberB() != 0){
    5. return getNumberA() / getNumberB();
    6. }
    7. throw new Exception("除数不能为0");
    8. }
    9. }

    4.6、简单工厂

    1. public class OperationFactory {
    2. public static Operation createOperate(String operate){
    3. Operation operation = null;
    4. switch (operate){
    5. case "+":
    6. operation = new OperationAdd();
    7. break;
    8. case "-":
    9. operation = new OperationSub();
    10. break;
    11. case "*":
    12. operation = new OperationMul();
    13. break;
    14. case"/":
    15. operation = new OperationDiv();
    16. break;
    17. }
    18. return operation;
    19. }
    20. }

    4.7、客户端

    1. public class Program {
    2. public static void main(String[] args) throws Exception {
    3. Operation operation;
    4. operation = OperationFactory.createOperate("+");
    5. operation.setNumberA(2);
    6. operation.setNumberB(4);
    7. double result = operation.getResult();
    8. System.out.println(result);
    9. }
    10. }

    5、简单工厂模式优点

    1、工厂类含有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的责任,而仅仅“消费”产品;简单工厂模式通过这种做法实现了对责任的分割,它提供了专门的工厂类用于创建对象。

    2、客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可,对于一些复杂的类名,通过简单工厂模式可以减少使用者的记忆量。

    3、通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。

    6、简单工厂模式缺点

    1、由于工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。

    2、使用简单工厂模式将会增加系统中类的个数,在一定程序上增加了系统的复杂度和理解难度。

    3、系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。

    4、简单工厂模式由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构。

    三、总结

    使用了简单工厂之后,如果有一天我们需要更改假发运算,只需要更改OperationAdd就可以了,如果需要增加各种复杂运算,例如:平方根、自然对数、正弦等,需要增加相应的运算子类,修改运算类工厂,在switch中增加分支,来看一下简单工厂的类结构。

  • 相关阅读:
    vue预览PDF文件的几种方法
    单元测试效率优化:为什么要对程序进行测试?测试有什么好处?
    基于Nuxtjs的同构渲染实践
    VR数字政务为我们带来了哪些便捷之处?
    在华为和比亚迪干了5年测试,月薪25K,熬夜总结出来的划水经验.....
    LabVIEW样式检查表10
    【Java 进阶篇】使用 Java 和 Jsoup 进行 XML 处理
    c++ 11 多线程支持 (std::future)
    【1day】用友U8Cloud未授权访问漏洞学习
    【JavaWeb】 Mybatis-02-Mybatis的快速入门
  • 原文地址:https://blog.csdn.net/wmj20001225/article/details/109963484