C# 一个计算器功能实现引发的思考

一.需求

    计算器功能需求,这个众所周知,很明确了。

二.步骤分析

1)初级实现计算器 

复制代码
  static int Calculator(int a,int b,string str)
        {
            switch(str)
            {
                case "+":
                    return a + b;
                case "-":
                    return a - b;
                case "*":
                    return a * b;
                case "/":
                    return a / b;
            }
            return 0;
        }
复制代码

    优势:代码简单。

    劣势:如果新增需求,需要不断在switch中增加分支,并且需要在对应分支写上相应的逻辑代码。代码耦合度太高。违背对修改关闭原则。

2)中级实现计算器

      I.先看case分支中对应的操作,都是运算。即,我们可以把其实现抽象出来。

      II.因为我们知道所有的运算都是对两个数进行运算,所以,可以抽象出一个抽象类,即运算抽象基类BaseCalculate。     

复制代码
public abstract class BaseCalculate
    {
        public abstract int Calculate(int a, int b);
    }

    public class Add : BaseCalculate
    {
        public override int Calculate(int a, int b)
        {
            return a + b;
        }
    }

    public class Sub:BaseCalculate
    {
        public override int Calculate(int a, int b)
        {
            return a - b;
        }
    }
复制代码

  优势:这个操作,我们将case中分支的代码抽象出来了。在对应的运算子类中更改其操作就可以。将具体实现抽离出来。

  劣势:代码量增加,违背了开放-封闭原则。(即开放增加,封闭修改原则)

  上述,就是设计模式中,传说的简单工厂模式

3)高级实现计算器

复制代码
 class Program
    {
        static void Main(string[] args)
        {
            BaseFactory factory = new AddFactory();
            Console.WriteLine(factory.GetCalculate().Calculate(2, 1));

            BaseFactory factory2 = new SubFactory();
            Console.WriteLine(factory2.GetCalculate().Calculate(2, 1));
            Console.Read();
        }
    }

    public abstract class BaseFactory
    {
        public abstract BaseCalculate GetCalculate();
    }


    public class AddFactory:BaseFactory
    {
        public override BaseCalculate GetCalculate()
        {
            return new Add();
        }
    }

    public class SubFactory:BaseFactory
    {
        public override BaseCalculate GetCalculate()
        {
            return new Sub();
        }
    }
复制代码

  这就是传说中工厂方法模式,与上述简单工厂模式对比克服了开放-封闭原则。

  优势:减去核心逻辑中的switch分支。

  劣势:代码量又增加了。

4)扩展&补充

  如果说上述的设计只为int型运算,如果现在需求增加,还需要增加 专门精度为float计算的计算器。上述计算,只针对int型,现在要专门是float型,该如何?

  所以,我们只需要增加基类BaseFloatCalculate,然后进行各种实现。并在BaseFactory中增加 BaseFactory GetFloatCalculate() 即可。代码就不贴了,这其实就是扩展。

  这就是抽象工厂模式。

  即使上述种种,还是离不开switch分支问题,有可以解决分支问题的办法吗。有的,但是不算主流,可以利用反射。

  BaseCalculate cal = (BaseCalculate)Assembly.Load("ConsoleApp7").CreateInstance("ConsoleApp7.Sub");
  Console.WriteLine( cal.Calculate(2, 1));

三.总结

    所谓优秀的功能的实现代码,即需要符合高聚酯,低耦合。

    符合高聚酯,低耦合,那就离不开架构设定。

    架构设计,其实无非就是即不断的抽象,对类抽象,对方法抽象。当然,也不能过度抽象,会造成冗余。

    因此总结一下,架构设定,就是合理适度的抽象。

    

    笔者认为

      没有绝对适合某功能的架构框架,只有绝对合理适度的抽象。

    

posted @   不三周助  阅读(655)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?

喜欢请打赏

扫描二维码打赏

了解更多

点击右上角即可分享
微信分享提示