zoukankan      html  css  js  c++  java
  • 第一节:开闭原则和里氏替换原则

    一. 开闭原则

    1. 定义

     对扩展开放,对修改关闭。(当应用的需求改变时,在不修改软件实体的源代码前提下,可以扩展模块的功能,使其满足新的需求。)

    2. 作用

    (1). 对软件测试的影响

     软件遵守开闭原则的话,软件测试时只需要对扩展的代码进行测试就可以了,因为原有的测试代码仍然能够正常运行。

    (2). 可以提高代码的可复用性

     粒度越小,被复用的可能性就越大;在面向对象的程序设计中,根据原子和抽象编程可以提高代码的可复用性。

    (3). 可以提高软件的可维护性

     遵守开闭原则的软件,其稳定性高和延续性强,从而易于扩展和维护

    3. 实现方法和案例 

     可以通过“抽象约束、封装变化”来实现开闭原则,即通过接口或者抽象类为软件实体定义一个相对稳定的抽象层,而将相同的可变因素封装在相同的具体实现类中。

     因为抽象灵活性好,适应性广,只要抽象的合理,可以基本保持软件架构的稳定。而软件中易变的细节可以从抽象派生来的实现类来进行扩展,当软件需要发生变化时,只需要根据需求重新派生一个实现类来扩展就可以了。

    PS: 依赖倒置原则就是对开闭原则很好的实现。

    类似的案例太多了,此处不单独提供了。

    二. 里氏替换原则

    1. 定义

     子类可以扩展父类的功能,但不要改变父类原有的功能。也就是说:子类继承父类时,除添加新的方法完成新增功能外,不要重写父类已经实现了的方法(抽象方法除外)。

    2. 作用

    (1). 里氏替换原则是实现开闭原则的重要方式之一。

    (2). 它避免了继承中重写父类造成的可复用性变差的缺点。

    (3). 它是动作正确性的保证。即类的扩展不会给已有的系统引入新的错误,降低了代码出错的可能性。

    3. 实现方法和案例

    父类和子类

      /// <summary>
        /// 计算父类
        /// </summary>
        public class FatherCalculate
        {
            /// <summary>
            /// 计算两个数相加
            /// </summary>
            /// <param name="a"></param>
            /// <param name="b"></param>
            /// <returns></returns>
            public int Cal1(int a,int b)
            {
                return a + b;
            }
    
            /// <summary>
            /// 计算两个数相加
            /// </summary>
            /// <param name="a"></param>
            /// <param name="b"></param>
            /// <returns></returns>
            public double Cal2(double a, double b)
            {
                return a + b;
            }
    
            /// <summary>
            /// 计算两个数相加
            /// </summary>
            /// <param name="a"></param>
            /// <param name="b"></param>
            /// <returns></returns>
            public virtual int Cal3(int a, int b)
            {
                return a + b;
            }
    
            /// <summary>
            /// 计算两个数相乘
            /// </summary>
            /// <param name="a"></param>
            /// <param name="b"></param>
            /// <returns></returns>
            public int Cal4(int a, int b)
            {
                return a * b;
            }
        }
    public class ChildCalculate2 : FatherCalculate
        {
            /// <summary>
            /// 计算两个数相减
            /// </summary>
            /// <param name="a"></param>
            /// <param name="b"></param>
            /// <returns></returns>
            public int Cal4(int a, int b)
            {
                return a - b;
            }
        }
    View Code

    测试

                {
                    Console.WriteLine("--------------------------里氏替换--------------------------------");
                    //父类中有加法和乘法运算
                    //1.执行加法运算
                    ChildCalculate1 c1 = new ChildCalculate1();
                    //计算错误,违背了里氏替换原则,子类重写了父类已经实现的方法,覆盖了父类
                    Console.WriteLine($"10+6={c1.Cal1(10, 6)}");    //4
    
                    //2.执行加法运算
                    FatherCalculate f1 = new ChildCalculate1();
                    //走的是父类的方法
                    Console.WriteLine($"10+6={f1.Cal1(10, 6)}");    //16
    
                    //3. 执行加法运算
                    FatherCalculate f2 = new ChildCalculate2();
                    //走的是父类的方法 (满足 里氏替换原则)
                    Console.WriteLine($"10+6={f2.Cal1(10, 6)}");     //16
    
                    //4. 执行加法运算
                    ChildCalculate2 c2 = new ChildCalculate2();
                    //走的是父类的方法,子类继承父类的 
                    Console.WriteLine($"10+6={c2.Cal1(10, 6)}");      //16
    
                    //5. 执行减法运算
                    //走的是子类的方法
                    Console.WriteLine($"10-6={c2.Cal4(10, 6)}");     //4
                }

    运行结果

     

    补充说明:如果通过重写父类的方法来完成新的功能,这样写起来虽然简单,但是整个继承体系的可复用性会比较差,特别是运用多态比较频繁时,程序运行出错的概率会非常大。

         如果程序违背了里氏替换原则,则继承类的对象在基类出现的地方会出现运行错误。这时其修正方法是:取消原来的继承关系,重新设计它们之间的关系。

     

     

     

    !

    • 作       者 : Yaopengfei(姚鹏飞)
    • 博客地址 : http://www.cnblogs.com/yaopengfei/
    • 声     明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
    • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
     
  • 相关阅读:
    149. Max Points on a Line(js)
    148. Sort List(js)
    147. Insertion Sort List(js)
    146. LRU Cache(js)
    145. Binary Tree Postorder Traversal(js)
    144. Binary Tree Preorder Traversal(js)
    143. Reorder List(js)
    142. Linked List Cycle II(js)
    141. Linked List Cycle(js)
    140. Word Break II(js)
  • 原文地址:https://www.cnblogs.com/yaopengfei/p/13527133.html
Copyright © 2011-2022 走看看