zoukankan      html  css  js  c++  java
  • c#六大设计原则(以仪器代码为例)

    [有格式的原文请到https://www.cnc6.cn/c六大设计原则/文末下载]

    软件设计原则常见的有6大原则,分别为:

    ①单一职责原则;

    ②开闭原则;

    ③依赖倒置原则;

    ④里氏替换原则;

    ⑤接口隔离原则;

    ⑥迪米特法则。

    使用C#编程方式,并结合仪器(Instrument)编程,对以上设计原则进行讲解。

    一、单一职责原则

    简述:类职责要单一,不能有多个职责,具有多个职责的类要进行拆分,形成单一职责的类。

    C#代码如下:

        class DCPowerSupply

        {

            public void On() { }

            public void Off() { }

            public double Voltage { set; get; }

            public double Current { set; get; }

            public void Record(string content)

            {

                //记录操作

            }

    }

    以上代码中,函数Off、On、Voltage、Current都是属于DCPowerSupply类的职责,但函数Record并不属于DCPowerSupply的职责,因此,需要将Record函数重新形成一个新类,并应用到该类中,新修改的C#代码如下:

        class DCPowerSupply

        {

            public void On() { }

            public void Off() { }

            public double Voltage { set; get; }

            public double Current { set; get; }

        }

        class Log

        {

            public void Record(string content)

            {

    //记录操作

            }

    }

    客户端代码如下:

        class Program

        {

            static void Main(string[] args)

            {

                DCPowerSupply dcPowerSupply = new DCPowerSupply();

                dcPowerSupply.Voltage = 5;

                dcPowerSupply.On();

                Log log = new Log();

                log.Record($"DCPowerSupply:{dcPowerSupply.Voltage},On");

            }

     }

    从以上代码可以看出,原本耦合性很强的DCPowerSupply中的函数Record,已经从该类中进行解耦,形成松耦合的代码,复用性更强。

    二、开闭原则

    简述:对类的操作,拓展的要开放,修改的要关闭,类一旦写好并运行OK,就不要轻易去变动它,利用面向对象编程的继承特性,可以很好地对所需要增加的功能进行拓展。

    C#代码如下:

        class ACPowerSupply

        {

            public void On() { }

            public void Off() { }

            public double Voltage { set; get; }

            public double Current { set; get; }

    }

    现在需要在ACPowerSupply类加入测量功率因素(PowerFactor)的功能,如果像这样修改ACPowerSupply类,C#代码如下:

        class ACPowerSupply

        {

            public void On() { }

            public void Off() { }

            public double Voltage { set; get; }

            public double Current { set; get; }

            public double PowerFactor { set; get; }

        }

    那就会违背了开闭原则,因ACPowerSupply类已经写好,如果要增加功能,可以新编写一个名为ACPowerSupplyEx的类,继承自ACPowerSupply,并在其中加入PowerFactor的功能即可。

    C#代码如下:

        class ACPowerSupplyEx:ACPowerSupply

        {

            public double PowerFactor { set; get; }

        }

    三、依赖倒置原则

    简述:抽象不依赖于具体细节,具体细节依赖抽象,要面向抽象编程,不要面向实现编程。说的简单点,无论是变量声明、返回值、还是参数,其类型都是抽象的,而不是具体的。

    鉴于以上特点:

    ①每个类尽量继承自接口或抽象类、或两者的结合体;

    ②每个类不应该从具体类派生;

    ③由于有使用继承,尽量参照里氏替换原则(以下第四点所述)。

    C#代码如下:

        class PowerSupply

        {

            public void On() { }

            public void Off() { }

            public double Voltage { set; get; }

            public double Current { set; get; }

        }

        class DCPowerSupply: PowerSupply

        {

            public double Power { set; get; }

        }

        class ACPowerSupply: PowerSupply

        {

            public double PowerFactor { set; get; }

    }

        class PowerSupplySeller

        {

            public void Sell(ACPowerSupply powerSupply)

            {

                //AC电源

            }

            public void Sell(DCPowerSupply powerSupply)

            {

                //DC电源

            }

     }

    客户端代码如下:

        class Program

        {

            static void Main(string[] args)

            {

                PowerSupplySeller seller = new PowerSupplySeller();

                seller.Sell(new ACPowerSupply());

                //下次想卖DC电源产品,就不得不在PowerSupplySeller类写入一个重载版的Sell方法,违背了开闭原则

            }

    }

    正确的C#代码如下(只需对public void Sell(ACPowerSupply powerSupply)进行修改即可):

        class PowerSupplySeller

        {

            public void Sell(PowerSupply powerSupply)

            {

                //ACDC电源

            }

    }

    客户端代码如下:

        class Program

        {

            static void Main(string[] args)

            {

                PowerSupplySeller seller = new PowerSupplySeller();

                seller.Sell(new ACPowerSupply());

                seller.Sell(new DCPowerSupply());

            }

     }

    以上不仅仅体现在形参上,还体现在方法或属性的返回值、字段类型等。

    四、里氏替换原则

    简述:可以使用父类的类型来代替子类的类型,但不改变子类的行为,继承必须确保父类所拥有的性质在子类中仍然成立。

    C#代码如下:

        class Meter

        {

            public double Voltage

            {

                get

                {

                    //模仿返回一个值,这里以5.01V为准

                    double value = 5.01;

                    Console.WriteLine($"DigitalMeter,Voltage:{value}");

                    return value;

                }

            }

            public double Current

            {

                get

                {

                    //模仿返回一个值,这里以1.001A为准

                    double value = 1.001;

                    Console.WriteLine($"DigitalMeter,Current:{value}");

                    return value;

                }

            }

        }

        class DigitalMeter: Meter

        {

        }

        class DCPowerSupply : Meter

        {

            public double Voltage

            {

                get

                {

                    //模仿返回一个值,这里以12.02V为准

                    double value = 12.02;

                    Console.WriteLine($"DCPowerSupply,Voltage:{value}");

                    return value;

                }

            }

            public double Current

            {

                get

                {

                    //模仿返回一个值,这里以2.002A为准

                    double value = 2.002;

                    Console.WriteLine($"DCPowerSupply,Current:{value}");

                    return value;

                }

            }

     }

    客户端代码如下:

        class Program

        {

            static void Main(string[] args)

            {

                Meter meter1 = new DigitalMeter();

                Meter meter2 = new DCPowerSupply();

                var voltage1 = meter1.Voltage;

                var voltage2 = meter2.Voltage;

                var current1 = meter1.Current;

                var current2 = meter2.Current;

            }

     }

    运行结果如下:

     

    从以上可以看出,本来为DCPowerSupply的类,既然输出了Meter的信息,这就违背了里氏替换原则。

    新修改的代码如下:

        interface IMeter

        {

            double Voltage { get; }

            double Current { get; }

        }

        class Meter: IMeter

        {

            public double Voltage

            {

                get

                {

                    //模仿返回一个值,这里以5.01V为准

                    double value = 5.01;

                    Console.WriteLine($"DigitalMeter,Voltage:{value}");

                    return value;

                }

            }

            public double Current

            {

                get

                {

                    //模仿返回一个值,这里以1.001A为准

                    double value = 1.001;

                    Console.WriteLine($"DigitalMeter,Current:{value}");

                    return value;

                }

            }

        }

        class DigitalMeter: Meter

        {

        }

        class DCPowerSupply : IMeter

        {

            public double Voltage

            {

                get

                {

                    //模仿返回一个值,这里以12.02V为准

                    double value = 12.02;

                    Console.WriteLine($"DCPowerSupply,Voltage:{value}");

                    return value;

                }

            }

            public double Current

            {

                get

                {

                    //模仿返回一个值,这里以2.002A为准

                    double value = 2.002;

                    Console.WriteLine($"DCPowerSupply,Current:{value}");

                    return value;

                }

            }

    }

    客户端代码如下:

        class Program

        {

            static void Main(string[] args)

            {

                IMeter meter1 = new DigitalMeter();

                IMeter meter2 = new DCPowerSupply();

                var voltage1 = meter1.Voltage;

                var voltage2 = meter2.Voltage;

                var current1 = meter1.Current;

                var current2 = meter2.Current;

            }

    }

    运行结果如下:

     

    从以上代码可以看出,用父类代替子类时,不能影响其子类的行为,否则,就违背了里氏替换原则。

    五、接口隔离原则

    简述:要让接口尽量简单,功能一致的可以写在仪器,与接口无关的必须重新写接口,也就是说,不要让接口变得臃肿。

    C#代码如下:

        interface IInstrument

        {

            void Write(string command);

            string Read();

            double Voltage { get; }

            double Current { get; }

    }

    以上代码有两组,一组为Write、Read,另外一组为Voltage、Current,按照功能分类的话,Write、Read应属于端口的读写,而Voltage、Current则为电表的读电压、读电流,按照接口隔离原则,需要进行隔离。

    修改后的代码如下:

        interface IPort

        {

            void Write(string command);

            string Read();

    }

        interface IMeter

        {

            double Voltage { get; }

            double Current { get; }

    }

    六、迪米特法则

    简述:类A、类B之间本身没有直接关联关系,那么就不能相互调用,可以通过第三个类(类C)进行间接调用,降低类A与类B的耦合性,提高模块的相对独立性。

    C#代码如下:

        class DCPowerSupply

        {

            public Port Port { set; get; }

            public double Voltage

            {

                set

                {

                    Port.Write($"Voltage:{value}");

                }

                get

                {

                    return Convert.ToDouble(Port.Read());

                }

            }

            public double Current

            {

                set

                {

                    Port.Write($"Current:{value}");

                }

                get

                {

                    return Convert.ToDouble(Port.Read());

                }

            }

            public void On() { }

            public void Off() { }

        }

        class Port

        {

            public void Write(string command)

            {

            }

            public string Read()

            {

                return new Random().NextDouble().ToString();

            }

        }

    以上代码,Port类与DCPowerSupply类进行了相互调用,耦合性很强,改变其中一个类的方法,对调用的那个类有很大的影响。

    修改之后的代码如下:

        class DCPowerSupply

        {

            public double Voltage { set; get; }

            public double Current { set; get; }

            public void On() { }

            public void Off() { }

        }

        class Port

        {

            public void Write(string command)

            {

            }

            public string Read()

            {

                return new Random().NextDouble().ToString();

            }

        }

        class DCPowerSupplyWithPort

        {

            DCPowerSupply powerSupply;

            Port port;

            public DCPowerSupplyWithPort()

            {

                powerSupply = new DCPowerSupply();

                port = new Port();

            }

            public double Voltage

            {

                set

                {

                    port.Write($"Voltage:{value}");

                }

                get

                {

                    return Convert.ToDouble(port.Read());

                }

            }

            public double Current

            {

                set

                {

                    port.Write($"Current:{value}");

                }

                get

                {

                    return Convert.ToDouble(port.Read());

                }

            }

            public void On()

            {

                powerSupply.On();

            }

            public void Off()

            {

                powerSupply.Off();

            }

        }

    以上代码,可以将Port类与DCPowerSupply类进行分离,使用了第三个类DCPowerSupplyWithPort,使得Port类与DCPowerSupply类松耦合,独立性强,符合迪米特法则,同样,该法则还适用于三层架构。

  • 相关阅读:
    js快速排序
    蛇形数组
    大臣的旅费
    1724ROADS
    2738:实数加法
    完整版高精度计算(整理后的)
    2737:大整数除法
    2980:大整数乘法
    2736大整数减法,3180 整数减法
    2981:大整数加法
  • 原文地址:https://www.cnblogs.com/cncc/p/11249254.html
Copyright © 2011-2022 走看看