首页 > 其他分享 >大话设计模式-简单工厂模式

大话设计模式-简单工厂模式

时间:2024-04-09 11:56:13浏览次数:23  
标签:strNumberA strNumberB double 大话 strResult 工厂 operation 设计模式 public

简单工厂模式

面向对象和面向过程

在大话设计模式中,为了引出简单工厂模式这一个话题,作者举了一个计算器的例子,通过不断的去优化计算器功能的实现代码,来帮助我们理解面向对象这一概念。

  1. 首先是初始的代码,逻辑简单明了,是面向过程的方法去解决的,用计算机的方式去思考问题,直接判断输入的符号,再进行相应的运算。对于简单的程序而言,这样做的好处就是直观,效率高。但是以这样的逻辑去编写的代码存在一个较大的缺陷,那就是局限性太大,只能满足当前的需求,当需求发生变化的时候,我们就需要再主函数中进行相应的修改,当需求复杂的时候,代码非常多,这样所有的逻辑写在一起,光看起来就费劲,万一改动的时候不小心改变了其它部分的代码,很容易出现问题,而且难以排查;除此之外,这样写的代码也没法复用,当我在其它地方使用时,还得把代码复制一份。
//面向过程c#
class Program {
    static void Main(string[] args) {
        try {
            Console.Write("请输入数字A:");
            string strNumberA = Console.ReadLine();
            Console.Write("请选择运算符号(+、-、*、/):");
            string strOperate = Console.ReadLine();
            Console.Write("请输入数字B:");
            string strNumberB = Console.ReadLine();
            string strResult = "";
            switch (strOperate) {
                case "+":
                    strResult =
                            Convert.ToString(Convert.ToDouble(strNumberA)
                                    + Convert.ToDouble(strNumberB));
                    break;
                case "-":
                    strResult = Convert.ToString(Convert.ToDouble(strNumberA) - Convert.ToDouble(strNumberB));
                    break;
                case "*":
                    strResult = Convert.ToString(Convert.ToDouble(strNumberA) * Convert.ToDouble(strNumberB));
                    break;
                case "/":
                    if (strNumberB != "0")
                        strResult = Convert.ToString(Convert.ToDouble(strNumberA) / Convert.ToDouble(strNumberB));
                    else
                        strResult = "除数不能为0";
                    break;
            }
            Console.WriteLine("结果是:" + strResult);
            Console.ReadLine();
        } catch (Exception ex) {
            Console.WriteLine("您的输入有错:" + ex.Message);
        }
    }
}
  1. 在讲到面向对象时,作者在文中举了一个非常形象的例子,那就是活字印刷:为每个字都做一个刻板,在印刷不同的文章时,只需更改字的顺序,在出现没印刷过的字时或者出现某个字刻错了的情况,只需要为这个字制作一个新的刻板,其它字的刻板照常使用。面向对象的优点就在于其通过封装、继承和多态的方式,让代码“分工明确,各司其职”,它将负责不同业务的代码分离,相互之间互不影响,这样做既解决了问题复杂时的代码冗余问题,又能够将刻好的“字”复用到其他地方。这样就做到了代码的易维护,易扩展和可复用。
////////////////////////
public class Operation {
    private double numberA = 0;
    private double numberB = 0;

    public Operation() {
    }

    public Operation(double numberA, double numberB) {
        this.numberA = numberA;
        this.numberB = numberB;
    }

    public double getNumberA() {
        return numberA;
    }

    public void setNumberA(double numberA) {
        this.numberA = numberA;
    }

    public double getNumberB() {
        return numberB;
    }

    public void setNumberB(double numberB) {
        this.numberB = numberB;
    }

    public double getResult() {
        return 0D;
    }
}
////////////////////////
public class OperationAdd extends Operation {
    public OperationAdd() {
    }

    public OperationAdd(double numberA, double numberB) {
        super(numberA, numberB);
    }

    @Override
    public double getResult() {
        return super.getNumberA() + super.getNumberB();
    }
}
////////////////////////
public class OperationDel extends Operation {
    public OperationDel() {
    }

    public OperationDel(double numberA, double numberB) {
        super(numberA, numberB);
    }

    @Override
    public double getResult() {
        return super.getNumberA() - super.getNumberB();
    }
}
////////////////////////
public class OperationDiv extends Operation {
    public OperationDiv() {
    }

    public OperationDiv(double numberA, double numberB) {
        super(numberA, numberB);
    }

    @Override
    public double getResult() {
        return super.getNumberA() / super.getNumberB();
    }
}
////////////////////////
public class OperationMul extends Operation {
    public OperationMul() {
    }

    public OperationMul(double numberA, double numberB) {
        super(numberA, numberB);
    }

    @Override
    public double getResult() {
        return super.getNumberA() * super.getNumberB();
    }
}
////////////////////////
  1. 上述代码定义了一个父类和四个字类,父类中可以存放一些公共的东西,比如操作数;然后在子类中重写父类的GetResult方法,不同的符号有着不同的运算逻辑,这样我们需要增加或者修改业务逻辑时,就只需要增加子类,或者修改其中某个子类,而不会影响到其它子类的使用,并且写好的子类可以在其他位置多次调用。调用方式如下所示:
import java.util.Scanner;

/**
 * @Author yirui
 * @Date 2024/4/9 10:26
 * @Version 1.0
 */
public class Program {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        try {
            System.out.println("请输入数字A:");
            Double strNumberA = sc.nextDouble();
            sc.nextLine(); // 清除换行符
            System.out.println("请选择运算符号(+、-、*、/):");
            String strOperate = sc.nextLine();
            System.out.println("请输入数字B:");
            Double strNumberB = sc.nextDouble();
            String strResult = "";
            Operation operation;
            switch (strOperate) {
                case "+":
                    operation = new OperationAdd(strNumberA, strNumberB);
                    strResult = String.valueOf(operation.getResult());
                    break;
                case "-":
                    operation = new OperationDel(strNumberA, strNumberB);
                    strResult = String.valueOf(operation.getResult());
                    break;
                case "*":
                    operation = new OperationMul(strNumberA, strNumberB);
                    strResult = String.valueOf(operation.getResult());
                    break;
                case "/":
                    if (strNumberB != 0D) {
                        operation = new OperationDiv(strNumberA, strNumberB);
                        strResult = String.valueOf(operation.getResult());
                        break;
                    } else {
                        strResult = "除数不能为0";
                    }
                    break;
            }
            System.out.println("结果是:" + strResult);
        } catch (Exception ex) {
            System.out.println("您的输入有错:" + ex.toString());
        } finally {
            sc.close();
        }
    }
}

简单工厂模式

上述计算器的计算过程虽然通过父子类之间的继承做到了易扩展,易维护和可复用,但是最后进行调用的代码任然过于复杂,我们只是把运算的业务逻辑分离出去了,而根据运算符去判断创建哪个对象的业务逻辑代码仍然和界面代码(从用户那儿获取数据的代码)放在一块,这样我们在新增一种运算规则的时候,仍然需要修改这里面的业务逻辑,仍然不够方便。在实际的开发过程中,我们应该尽可能的把界面逻辑和业务逻辑分离开,降低他们之间的耦合度,这样才能够真正的做到易维护和易扩展,于是作者就引出了简单工厂模式。

  1. 所谓“工厂”,就是专门生产东西的地方,而在Java中,就是生产对象的地方,我们的四个字类都与运算相关,那我们就可以制造一个运算工厂,专门来为我们创建与运算有关的对象,这样做的好处就是:在我们用户看来,我不需要关心你这个“东西”具体的生产过程,我只需要把材料给你,然后你把结果给我。
public class OperationFactory {
    public static Operation createOperation(Double strNumberA, Double strNumberB,String strOperate) throws Exception{
        Operation operation = null;
        switch (strOperate) {
            case "+":
                operation = new OperationAdd(strNumberA,strNumberB);
                break;
            case "-":
                operation = new OperationDel(strNumberA,strNumberB);
                break;
            case "*":
                operation = new OperationMul(strNumberA,strNumberB);
                break;
            case "/":
                if (strNumberB != 0D){
                    operation = new OperationDiv(strNumberA,strNumberB);
                    break;
                } else {
                    throw new Exception("除数不能为0!");
                }
        }
        return operation;
    }
}
  1. 有了这个工厂之后,客户端的代码就变成了这样,以后即使新增了计算规则,我们也只需要新增子类,并且修改工厂类中的业务逻辑,而客户端的代码只专注于界面逻辑(改改提示信息或者界面即可),不包含业务逻辑相关的修改。
import java.util.Scanner;

/**
 * @Author yirui
 * @Date 2024/4/9 11:18
 * @Version 1.0
 */
public class Program2 {
    public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
        try {
        System.out.println("请输入数字A:");
        Double strNumberA = sc.nextDouble();
        sc.nextLine();//清除回车符
        System.out.println("请选择运算符号(+、-、*、/):");
        String strOperate = sc.nextLine();
        System.out.println("请输入数字B:");
        Double strNumberB = sc.nextDouble();
        String strResult = "";
        Operation operation = OperationFactory.createOperation(strNumberA,strNumberB,strOperate);
        strResult = String.valueOf(operation.getResult());
        System.out.println("结果是:" + strResult);
    } catch (Exception ex) {
        System.out.println("您的输入有错:" + ex.toString());
    } finally {
        sc.close();
    }
}
}

总结

面向对象和面向过程的区别

以我的浅薄理解,他们的区别大致可以分为三个方面:思路不同,特点不同和优势不同

  • 面向过程的思路是以过程为核心关注解决一个问题的具体实施流程是什么样的,按照流程去编写函数,一步一步实现最终的目标,它的优点是对于不复杂的问题实现效率高,但是面对复杂的问题时,流程可能会非常繁琐,维护起来会很困难。

  • 而面向对象的思路则是以对象为核心关注一个问题中有哪些角色或者可以分为哪几块功能,每个角色或者每个功能模块只关注自己具有哪些属性和功能,将这些角色或者模块封装成一个一个的对象,通过调用对象的方法或者属性解决最终的问题;面向对象的设计思路相较于面向过程而言可能会更加繁琐,但是当面对较为复杂的问题时,面向对象的方法可以将问题拆分的更加清楚,维护起来更加简单;并且具有高度的扩展性和复用性。

为什么要用简单工厂模式

简单工厂模式是一种创建型设计模式,其本质在于对对象创建过程的抽象。它的作用和优点主要可以概括如下:

  • 分离对象创建使用的职责
    在不使用简单工厂模式时,客户端代码需要直接创建对象,这可能涉及到一连串的代码来构造对象。对象的创建逻辑和界面逻辑混合在一起,不方便管理。
    使用简单工厂模式,我们将对象创建的具体逻辑隐藏起来,交给工厂类来管理。这样,客户端只需知道具体产品类所对应的参数,而无需关心对象的实例化过程。这种分离可以减少代码量,提高代码的可读性和可维护性
  • 灵活性和扩展性
    当业务场景发生变化时,我们可以通过引入配置文件或其他方式,在不修改客户端代码的情况下更换和增加新的具体产品类。
    如果需要增加一种类型的产品,只需修改工厂类中的操作代码,而不需要修改客户端代码。这提高了系统的灵活性和可扩展性。
    总之,简单工厂模式有助于将对象创建的过程抽象出来,使代码更易于维护和扩展。它适用于需要多态性的场景,同时也可以用于减少代码侵入性的情况。

标签:strNumberA,strNumberB,double,大话,strResult,工厂,operation,设计模式,public
From: https://www.cnblogs.com/yirui/p/18122264/yiruiblog

相关文章

  • 设计模式之观察者模式讲解
    概念:定义对象间一种一对多的依赖关系,使得当每一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。抽象主题:或者叫被观察者,可以持有、增加、删除观察者对象。具体主题:实现抽象主题定义的操作,并定义一个状态,每当状态改变时,通知所有观察者。抽象观察者:为所有观察......
  • 设计模式 - 策略模式
    起初业务简单、随着业务增长所有相关业务代码处理逻辑都放置同一个对象中,通过策略模式以不通分类实现具体业务publicinterfaceIPlanVideoStrategy{Stringexecute(IntegertypeCode,IntegernodeId,List<String>qzTimeList);}publicclassPlanPlayBackContext{......
  • HG6821M开启工厂模式
    本帖最后由小圆于2020-5-2219:16编辑开启不是永久的,是一次性的浏览器访问http://192.168.1.1/cgi-bin/telnetenable.cgi?telnetenable=1,然后打开终端telnet192.168.1.1使用用户名:root密码:hg2x0登陆登陆成功之后cd/usr/protest/mftouch/usr/protest/mf/factory_......
  • 为大家整理最全的24种设计模式详解,必收藏
    设计模式六大原则 单一职责原则一个方法尽可能做一件事情,一般来说不应该让一个方法承担多个职责。单一职责原则的英文名称是SingleResponsibilityPrinciple,简称是SRP。单一职责原则的定义是:应该有且仅有一个原因引起类的变更。SRP的原话解释是:Thereshouldneverbemo......
  • 浅尝设计模式
    设计模式三大类创建型模式工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式结构型模式适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式行为型模式策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备......
  • 设计模式|责任链模式(Chain of Responsibility Pattern)
    文章目录结构优点缺点使用责任链的步骤示例有哪些知名框架采用了责任链模式责任链模式和链表有什么关联常见面试题责任链模式(ChainofResponsibilityPattern)是一种行为设计模式,它允许你创建一个对象链。请求将沿着这个链传递,直到有一个对象处理它为止。这种模式可以......
  • 设计模式-建造者模式
    1.概念建造者模式(BuilderPattern)又叫生成器模式,是一种创建型设计模式,用于将复杂对象的构建过程与其表示分离,以便相同的构建过程可以创建不同的表示。这种模式特别适用于创建那些具有多个组成部分、步骤复杂或者产品具有多种不同变化的对象。2.原理结构图原理结构图......
  • 设计模式 - 代理模式
    使用代理对象,我们可以对与某些对象的交互进行更多的控制。代理对象可以在我们与对象进行交互时确定其行为,例如,当我们获取值或设置值时。一般来说,代理是指代替他人的人。你不是直接和那个人说话,而是和代表你试图联系的人说话的代理。在JavaScript中也是如此:我们不是直接与目标......
  • C++设计模式:TemplateMethod模式(一)
    1、概念定义定义一个操作中的算法的骨架结构(稳定),而将一些步骤延迟(变化)到子类中。TemplateMethod使得子类可以不改变(复用)一个算法的骨架结构即可重定义(override重写)该算法的某些特定步骤在软件构建过程中,对于某一项任务,它常常有稳定的整体操作结构,但是各个子步骤却有很......
  • 毅四捕Go设计模式笔记——桥接模式
    桥接模式(BridgePattern)桥接模式是一种结构型设计模式,它的主要目的是将抽象部分与它的实现部分解耦,使它们都可以独立的变化。通过使用组合而非继承的方式,桥接模式结合了两个独立的维度,让它们可以独立扩展而不是在两者之间建立静态的继承关系。为了解决什么问题?桥接模式解......