zoukankan      html  css  js  c++  java
  • 面向对象六大原则(上)

    单一职责原则

    单一职责原则(Single Responsibility Principle, SRP)简而言之就是对于一个类或者接口, 引起其改变的应该只能有一个原因. 比如要将负责属性和行为的类分开.

    里氏替换原则

    定义:所有引用基类的地方必须能透明地使用其子类的对象. 只要父类出现的地方, 子类就可以出现, 而且替换为子类不会产生任何错误或者一场. 但是反过来不一定可行.

    1. 子类中可以增加自己特有的方法。
    2. 当子类的方法重载父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。
    3. 当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。

    前置条件

    当子类的方法重载父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。

    class Father {
    
        public Collection doSomething(HashMap map){
            StdOut.println("父类被执行...");
            return map.values();
        }
    }
    
    class Son extends Father{
    
        public Collection doSomething(Map map) {
            StdOut.println("子类被执行");
            return map.values();
        }
    }

    子类方法和父类方法, 方法名相同, 返回类型相同, 但是参数不同, 所以不是Override, 而是Overload. 在这种情况下, 如果传入HashMap, 子类的doSomething()不会被执行.
    这是正确的, 因为子类并没有重写父类方法, 而是重载父类方法, 所以如果父类的前置条件(形参) 范围宽于子类则不正确.

    public static void main(String[] args){
        Father f=new Father();
        HashMap map=new HashMap();
        f.doSomething(map);
    }
    
    父类被执行
    public static void main(String[] args){
        //父类出现的地方都可以被子类代替, 且不会改变逻辑
        Son f=new Son();
        HashMap map=new HashMap();
        f.doSomething(map);
    }
    
    父类被执行
    public static void main(String[] args){
       //子类出现的地方, 父类不一定可以代替
        Son f=new Son();
        Map map=new HashMap();
        f.doSomething(map);
    }
    
    子类被执行
    class Father {
    
        public Collection doSomething(Map map){
            StdOut.println("父类被执行...");
            return map.values();
        }
    }
    
    class Son extends Father{
    
        public Collection doSomething(HashMap map) {
            StdOut.println("子类被执行");
            return map.values();
        }
    }
    public static void main(String[] args){
        Father f=new Father();
        HashMap map=new HashMap();
        f.doSomething(map);
    }
    
    父类被执行
    public static void main(String[] args){
        //父类出现的地方都可以用子类代替
        Son f=new Son();
        HashMap map=new HashMap();
        f.doSomething(map);
    }
    
    子类被执行

    可以注意到, 此时子类方法被执行了, 而子类并没有重写父类的相应的方法, 而是重载了父类的方法.

    public static void main(String[] args){
        Son f=new Son();
        Map map=new HashMap();
        f.doSomething(map);
    }
    
    父类被执行

    后置条件

    当子类的方法实现或覆写父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格或相同。

    注意点

    1. 在类中调用其他类时务必使用其父类或者接口, 如果不能使用父类或者接口, 则说明类的设计已经违背了LSP原则.
    2. 如果子类不能完整地实现父类的方法, 或者父类的一些方法在子类中完全和父类业务逻辑不同, 则建议不使用继承关系, 而是用依赖, 聚集, 组合等关系代替.

    依赖倒置原则

    Dependence Inversion Principle

    1. 高层模块不应该依赖低层模块
    2. 抽象不应该依赖细节
    3. 细节应依赖抽象
    名称 含义
    高层模块 原子逻辑再组装就是高层模块
    低层模块 每一个逻辑的实现都由院子逻辑组成,不分割的原子逻辑就是低层模块

    对于Java来说.

    1. 模块间的依赖通过抽象产生,实现类之间不发生直接依赖关系, 其依赖关系是通过接口或者抽象类产生的
    2. 接口或这抽象类不依赖于实现类
    3. 实现类依赖接口或抽象类

    这样也有利于并行开发, 即使只完成了一部分工作, 仍可以进行单元测试.

    这也符合现代开发的流程, 先写好单元测试类, 再写实现类.

    规则

    1. 每个类尽量都有接口或抽象类, 或者抽象类和接口都具备
    2. 变量的表面类型尽量是接口或者是抽象类(如果使用类的clone方法, 就必须使用实现类)
    3. 任何类都不应该从具体类中派生(如果实在需要继承自具体类, 尽量不要超过两层的继承)
    4. 尽量不要覆写基类的方法

    总体而言, 依赖倒置原则是六大原则中最难实现的, 也是实现开闭原则的重要途径. 总体而言, 把握住面向接口编程即可.

  • 相关阅读:
    DirectX11 With Windows SDK--14 深度测试
    DirectX11 With Windows SDK--12 深度/模板状态、平面镜反射绘制
    DirectX11--深入理解HLSL常量缓冲区打包规则
    JS学习笔记7_表单脚本
    JS学习笔记6_事件
    JS学习笔记5_DOM
    JS学习笔记4_BOM
    JS学习笔记3_函数表达式
    JS学习笔记2_面向对象
    JS学习笔记1_基础与常识
  • 原文地址:https://www.cnblogs.com/fei-hsueh/p/6106301.html
Copyright © 2011-2022 走看看