c # and six design principles (with instrument code as an example)

[There format text go https://www.cnc6.cn/c six design principles / end of the text Download]

 

Software design principles common are six principles, namely:

① single responsibility principle;

② opening and closing principle;

③ Dependency Inversion Principle;

④ Richter substitution principle;

⑤ Interface segregation principle;

⑥ Demeter.

Use C # programming, combined instrument (Instrument) program, the above design principles to explain.

A single responsibility principle

Description: to a single class of functions, can not have multiple duties, responsibilities to a plurality of classes having a split, forming a single class of functions.

C # code is as follows:

    class DCPowerSupply

    {

        public void On() { }

        public void Off() { }

        public double Voltage { set; get; }

        public double Current { set; get; }

 

        public void Record(string content)

        {

            // recording operation

        }

}

Above, the function Off, On, Voltage, Current belong DCPowerSupply responsibility category, but the function Record does not belong DCPowerSupply responsibility, therefore, necessary to Record function to form a new class, and apply to the class, a new modified following C # code:

    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)

        {

// recording operation

        }

}

Client code as follows:

    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");

        }

 }

As can be seen from the above code, the original highly coupled DCPowerSupply function of Record, has been decoupled from the genus, the code is formed of loosely coupled, greater reusability.

Second, the opening and closing principle

Description: type of operation, expanding to open, edit To close, class, once written and run OK, it is not easy to change it, use the inheritance feature of object-oriented programming, you can be well on the need to increase function expansion.

C # code is as follows:

    class ACPowerSupply

    {

        public void On() { }

        public void Off() { }

        public double Voltage { set; get; }

        public double Current { set; get; }

}

Now requires ACPowerSupply added category measured power factor ( powerfactor) function, as if such modifications ACPowerSupply class, C # code is as follows:

    class ACPowerSupply

    {

        public void On() { }

        public void Off() { }

        public double Voltage { set; get; }

        public double Current { set; get; }

        public double PowerFactor { set; get; }

    }

That would be contrary to the principle of opening and closing, because ACPowerSupply class has been written, if you want to add functionality, you can write a new named class ACPowerSupplyEx, inheritance from ACPowerSupply , and adding PowerFactor the function.

C # code is as follows:

    class ACPowerSupplyEx:ACPowerSupply

    {

        public double PowerFactor { set; get; }

    }

Third, the Dependency Inversion Principle

Description: Abstract does not depend on the details, details depend abstract to abstract-oriented programming, do not realize oriented programming. Simple point, whether it is a variable declaration, return values, or parameters, their types are abstract, not concrete.

In view of the above characteristics:

① each possible class inherits from an abstract class or an interface, or a combination of both;

② Each class should not derive from specific classes;

③ Because of the use of inheritance, as far as possible with reference to the principle of replacing Richter (hereinafter, the fourth point).

C # code is as follows:

    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)

        {

            // sell AC power supply

        }

        public void Sell(DCPowerSupply powerSupply)

        {

            // Sell DC power supply

        }

 }

 

Client code as follows:

    class Program

    {

        static void Main(string[] args)

        {

            PowerSupplySeller seller = new PowerSupplySeller();

            seller.Sell(new ACPowerSupply());

            // next want to sell DC power products, you have to PowerSupplySeller write a heavy-duty version of the class Sell method, contrary to the principle of opening and closing

        }

}

Correct C # code as follows (only for public void Sell (ACPowerSupply powerSupply) to be modified):

    class PowerSupplySeller

    {

        public void Sell(PowerSupply powerSupply)

        {

            // sell AC or DC power supply

        }

}

Client code as follows:

    class Program

    {

        static void Main(string[] args)

        {

            PowerSupplySeller seller = new PowerSupplySeller();

            seller.Sell(new ACPowerSupply());

            seller.Sell(new DCPowerSupply());

        }

 }

Not reflected in the above parameter is also reflected in the return value of the property or the method, the field types.

Fourth, Richter substitution principle

Description: You can use the type of parent class instead of the subclass type, but does not change the behavior of the subclass inherits the parent must ensure owned properties still hold in the subclass.

C # code is as follows:

    class Meter

    {

        public double Voltage

        {

            get

            {

                // imitate returns a value, here to 5.01V prevail

                double value = 5.01;

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

                return value;

            }

        }

 

        public double Current

        {

            get

            {

                // imitate returns a value, here to 1.001A prevail

                double value = 1.001;

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

                return value;

            }

        }

    }

 

    class DigitalMeter: Meter

    {

 

    }

 

    class DCPowerSupply : Meter

    {

        public double Voltage

        {

            get

            {

                // imitate returns a value, here to 12.02V prevail

                double value = 12.02;

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

                return value;

            }

        }

 

        public double Current

        {

            get

            {

                // imitate returns a value, here to 2.002A prevail

                double value = 2.002;

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

                return value;

            }

        }

 }

Client code as follows:

    class Program

    {

        static void Main(string[] args)

        {

            Meter meter1 = new DigitalMeter();

            Meter meter2 = new DCPowerSupply();

            var voltage1 = meter1.Voltage;

            was voltage2 = meter2.Voltage;

            var current1 = meter1.Current;

            var current2 = meter2.Current;

        }

 }

Results are as follows:

 

As can be seen from the above, would have to DCPowerSupply class, since information Meter's output, which is contrary to the principle of replacing Richter.

The new code is modified as follows:

    interface IMeter

    {

        double Voltage { get; }

        double Current { get; }

    }

 

    class Meter: IMeter

    {

        public double Voltage

        {

            get

            {

                // imitate returns a value, here to 5.01V prevail

                double value = 5.01;

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

                return value;

            }

        }

 

        public double Current

        {

            get

            {

                // imitate returns a value, here to 1.001A prevail

                double value = 1.001;

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

                return value;

            }

        }

    }

 

    class DigitalMeter: Meter

    {

 

    }

 

    class DCPowerSupply : IMeter

    {

        public double Voltage

        {

            get

            {

                // imitate returns a value, here to 12.02V prevail

                double value = 12.02;

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

                return value;

            }

        }

 

        public double Current

        {

            get

            {

                // imitate returns a value, here to 2.002A prevail

                double value = 2.002;

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

                return value;

            }

        }

}

Client code as follows:

    class Program

    {

        static void Main(string[] args)

        {

            IMeter meter1 = new DigitalMeter ();

            IMeter meter2 = new DCPowerSupply();

            var voltage1 = meter1.Voltage;

            was voltage2 = meter2.Voltage;

            var current1 = meter1.Current;

            var current2 = meter2.Current;

        }

}

Results are as follows:

 

As can be seen from the above code, when used instead of a subclass of a parent class, it can not affect the behavior of its subclasses, otherwise, they are violating the principles of replacement Richter.

Fifth, the interface segregation principle

Description: make the interface as simple as possible, consistent function can be written on the instrument, the interface has nothing to do with the need to re-write interface, that is to say, do not let the interface becomes bloated.

C # code is as follows:

    interface IInstrument

    {

        void Write(string command);

        string Read();

        double Voltage { get; }

        double Current { get; }

}

This code has two groups of Write, Read, another group of Voltage, Current, according to functional classification of words, Write, Read should belong to read and write ports, and Voltage, Current meter was read voltage, a read current, according to the interface segregation principle, we need to be isolated.

The modified code as follows:

    interface IPort

    {

        void Write(string command);

        string Read();

}

 

    interface IMeter

    {

        double Voltage { get; }

        double Current { get; }

}

Sixth, Demeter

Description: class A, does not have a direct relationship between the class B, then it can not call each other, can be an indirect call via a third category (category C), to reduce the coupling A and class B, class, increasing the relative module independence.

C # code is as follows:

    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();

        }

    }

The above code, Port DCPowerSupply class and class were calling each other, a strong coupling method in which a change of class, have a great impact on the type of call.

After the code is modified as follows:

    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();

        }

    }

The above code, the Port class DCPowerSupply class can be separated, a third category DCPowerSupplyWithPort, so that the Port class class DCPowerSupply loosely coupled, independent, Demeter meet Similarly, the rule is also applicable to three-tier architecture .

 

Guess you like

Origin www.cnblogs.com/cncc/p/11249254.html