zoukankan      html  css  js  c++  java
  • SOLID面向对象设计原则

     

    SRP

    The Single Responsibility Principle

    单一责任原则

    OCP

    The Open Closed Principle

    开放封闭原则

    LSP

    The Liskov Substitution Principle

    里氏替换原则

    ISP

    The Interface Segregation Principle

    接口分离原则

    DIP

    The Dependency Inversion Principle

    依赖倒置原则

     

    SOLID--固体、稳定的

    solid是5个原则的缩写,这样的设计具有稳定、可靠的特点。

    单一职责SRP

    一个类有且只有一个职责引起类改变的原因,只能有一个

    //接口、方法 更容易实现此原则

    任意小的改变都将导致这个单一类的变化。如果遵守 SRP,类将变得简洁和灵活

    核心是把整个问题分为小部分,并且每个小部分都将通过一个单独的类负责。

    public class Tank

    {//坦克类,业务逻辑和界面混合在一起

        public void Move()

        {

            //left

            //up

            //right

            //down

        }

        public void Show()

        {

            //windows show

        }

    }

    //新需求:linux

    面对新的需求,如何复用逻辑代码?

    因此,应该将职责分离,降低耦合。

     

    开放封闭原则

    个类应该对扩展开放,对修改关闭

    类已经开始使用,就不应该再修改。因为如果改变它,很可能你的改变会引发系统的崩溃。如果需要一些额外功能,应该扩展这个类而不是修改它

    使用这种方式,现有系统不会看到任何新变化的影响。同时,只需要测试新创建的类。

    public class Calculator

    {     //加减计算器

        public double Calculate(double firstNumber,    double secondNumber, string operate)

        {

            double result = 0d;

            switch (operate)

            {

                case “+":

                    result= firstNumber+ secondNumber;

                    break;

                case “-":

                    result= firstNumber- secondNumber;

                    break;

            }

            return result;

        }

    }

    新需求:加入乘除功能

    修改原来的类?影响到原有的功能怎么办?

    更好的设计:

        public class Operation

        {    //抽象父类,拥有基本属性

            public double NumberA

            {

            }

           public double NumberB

            {

            }

            public virtual double GetResult()

            {

                double result = 0;

                return result;

            }

    }

    class OperationMul : Operation

        { //拓展的乘法子类,增加新功能时,直接增加一个类,而不是修改原来的代码

            public override double GetResult()

            {

                double result = 0;

                result = NumberA * NumberB;

                return result;

            }

        }

    也就是封装变化,把频繁改动的地方抽象

     

    LSP里式替换

    类出现的地方皆可以换成子类

    上层模块不应关心底层模块的是如何工作的;同样的接口模块之间,可以在不知道底层模块代码的情况下,进行替换。即接口或父类出现的地方,实现接口的类或子类可以代入。

    class Program

     {

            static void Main(string[] args)

            {

                Animal animal = new   Animal();//新来一只牛(猫,狗,羊),要修改整个方法吗?

                animal.Show();    //或者拓展了Animal类,上层客户端的代码都要改动吗

                animal.Eat();

                animal.Run();

            }

      }

    public class Cat:Animal

    {    //子类继承Animal,是对父类的拓展

    }

    //Animal animal = new Cat();//使用继承&&多态,尽可能修改少的代码

    正因为子类型的替换,才使得父类无须修改就可以扩展,

    父类真正被服用,子类在此基础上增加新的行为

    注意:父类和子类须严格遵循is-a关系

     

    接口隔离原则(ISP

    不应该被迫依赖他们不使用的方法,也就是说一个接口应该拥有尽可能少的行为,它是精简的,也是单一的。

    使用多个专门的接口比使用单一的总接口要好

    不应该依赖大的接口,应该裁减为小的接口给客户模块使用,以减少依赖性

    public interface Animal

    {

            public void eat();      //

            public void sleep();    //

            public void crawl();     //

            public void run();      //

     }

    public class Bird Animal

    {   

      public void eat()

      {

      }

      public void sleep()

      {

      }

      public void crawl ()

      {单独抽取出接口!

      //鸟是动物,但不会

      }

      public void run()

      {单独抽取出接口!

          //鸟也不会

      }

    }

    依赖注入或倒置原则(DIP

    1. 高层模块不应该依赖于低层模块,二者都应该依赖于抽象 
    2. 抽象不应该依赖于细节,细节应该依赖于抽象

    public class Manager

    {

            public Notify notify = new Notify();//老式的调用

    }

    public class Notify

    {

            // Notify something

    }

    第一,当需要追加提供一种新的Notify时,对Manager层进行改动,增加了额外的工作。

    第二,这种改动可能会影响到Manager ,带来风险。

    第三,改动后, Manager层必须重新再做测试。

      public interface INotify

       {

            void Notify();

       }

    public class Manager:INotify

    {

      //do something

     public void Notify()

     {//只需要维护一个面向底层的接口,改动变小,尽可能遵守开闭原则

       //亦可以使用反射或上层传参的方式完全封闭这个类

    public INotify notify = new EmailNotify();

     }

      //do somgthing

    }

       public class EmailNotify:INotify

        {

            //EmailNotify

        }

        public class PhoneNotify:INotify

        {

            //PhoneNotify

        }

    总结

    个对象只承担一种责任,所有服务接口只通过它来执行这种任务。

    扩展行为开放,向修改行为关闭。

    子类应该可以用来替代它所继承的类。

    一个类对另一个类的依赖应该限制在最小化的接口上。

    依赖抽象层(接口、抽象类),而不是具体类。

     

    好处:

    高内聚低耦合

    简洁明了

    可读性高

    可维护性高

    良好的设计、尽可能避免问题的出现

    问题出现时,尽早的解决、低风险

     

    通常,符合这样的设计规范的代码就是简短、灵活、易懂,也就是,好的代码!

  • 相关阅读:
    python反射
    numpy笔记
    leetcode43
    leetcode-42
    The Github Flow
    leetcode-37
    leetcode-41
    leetcode-40
    TCP扫盲2
    字节码分析与操作
  • 原文地址:https://www.cnblogs.com/Zdelta/p/14122344.html
Copyright © 2011-2022 走看看