晚春复习——七大原则

158 阅读5分钟

本文的所以认知和理解来自 c.biancheng.net/view/1326.h…

七大原则

开闭原则

开闭原则 :当应用的需求改变时,在不修改软件实体的源代码或者二进制代码的前提下,可以扩展模块的功能,使其满足新的需求。对子类只增加,这样功能就越来越多了。

开闭原则的作用

开闭原则是面向对象程序设计的终极目标,它使软件实体拥有一定的适应性和灵活性的同时具备稳定性和延续性。

1.对软件测试的影响

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

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

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

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

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

image.png 上图中,每个子类(具体主体)都重写ABstractSubject接口的display方法,实现自己的展示方法,来体现自己的特点。

里氏替换原则的定义

里氏替换原则:子类可以扩展父类的功能,但不能改变父类原有的功能。也就是说:子类继承父类时,除添加新的方法完成新增功能外,尽量不要重写父类的方法。

image.png 几维鸟不会飞,而默认了鸟会飞,如果拓展的话就会出现异常。 所以为了保证安全子类(几维鸟)不能改变父类(鸟会飞)的功能。修改方法 鸟多两个子类,会飞的鸟和不会飞的鸟来解决。

依赖倒置原则的定义

依赖倒置原则 定义 :高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。
依赖倒置原则的目的是通过要面向接口的编程来降低类间的耦合性,所以我们在实际编程中只要遵循以下4点,就能在项目中满足这个规则。

  • 每个类尽量提供接口或抽象类,或者两者都具备。
  • 变量的声明类型尽量是接口或者是抽象类。
  • 任何类都不应该从具体类派生。
  • 使用继承时尽量遵循里氏替换原则。

举例

image.png


public class DIPtest {
    public static void main(String[] args) {
        Customer wang = new Customer();
        System.out.println("顾客购买以下商品:");
        wang.shopping(new ShaoguanShop());
        wang.shopping(new WuyuanShop());
    }
}

//商店
interface Shop {
    public String sell(); //卖
}

//韶关网店
class ShaoguanShop implements Shop {
    public String sell() {
        return "韶关土特产:香菇、木耳……";
    }
}

//婺源网店
class WuyuanShop implements Shop {
    public String sell() {
        return "婺源土特产:绿茶、酒糟鱼……";
    }
}

//顾客
class Customer {
    public void shopping(Shop shop) {
        //购物
        System.out.println(shop.sell());
    }
}

单一原则

单一职责原则规定一个类应该有且仅有一个引起它变化的原因,否则类应该被拆分。 单一职责原则的核心就是控制类的粒度大小、将对象解耦、提高其内聚性。如果遵循单一职责原则将有以下优点。

  • 降低类的复杂度。一个类只负责一项职责,其逻辑肯定要比负责多项职责简单得多。
  • 提高类的可读性。复杂性降低,自然其可读性会提高。
  • 提高系统的可维护性。可读性提高,那自然更容易维护了。
  • 变更引起的风险降低。变更是必然的,如果单一职责原则遵守得好,当修改一个功能时,可以显著降低对其他功能的影响。 你想管很多事吗?不想对吧?类也不想! 举例

image.png

接口隔离原则

接口隔离原则要为各个类建立它们需要的专用接口,而不要试图去建立一个很庞大的接口供所有依赖它的类去调用。
接口隔离原则和单一职责都是为了提高类的内聚性、降低它们之间的耦合性,体现了封装的思想,但两者是不同的:

  • 单一职责原则注重的是职责,而接口隔离原则注重的是对接口依赖的隔离。
  • 单一职责原则主要是约束类,它针对的是程序中的实现和细节;接口隔离原则主要约束接口,主要针对抽象和程序整体框架的构建。

image.png


public class ISPtest {
    public static void main(String[] args) {
        InputModule input = StuScoreList.getInputModule();
        CountModule count = StuScoreList.getCountModule();
        PrintModule print = StuScoreList.getPrintModule();
        input.insert();
        count.countTotalScore();
        print.printStuInfo();
        //print.delete();
    }
}

//输入模块接口
interface InputModule {
    void insert();

    void delete();

    void modify();
}

//统计模块接口
interface CountModule {
    void countTotalScore();

    void countAverage();
}

//打印模块接口
interface PrintModule {
    void printStuInfo();

    void queryStuInfo();
}

//实现类
class StuScoreList implements InputModule, CountModule, PrintModule {
    private StuScoreList() {
    }

    public static InputModule getInputModule() {
        return (InputModule) new StuScoreList();
    }

    public static CountModule getCountModule() {
        return (CountModule) new StuScoreList();
    }

    public static PrintModule getPrintModule() {
        return (PrintModule) new StuScoreList();
    }

    public void insert() {
        System.out.println("输入模块的insert()方法被调用!");
    }

    public void delete() {
        System.out.println("输入模块的delete()方法被调用!");
    }

    public void modify() {
        System.out.println("输入模块的modify()方法被调用!");
    }

    public void countTotalScore() {
        System.out.println("统计模块的countTotalScore()方法被调用!");
    }

    public void countAverage() {
        System.out.println("统计模块的countAverage()方法被调用!");
    }

    public void printStuInfo() {
        System.out.println("打印模块的printStuInfo()方法被调用!");
    }

    public void queryStuInfo() {
        System.out.println("打印模块的queryStuInfo()方法被调用!");
    }
}

迪米特法则的定义

迪米特法则的定义是:只与你的直接朋友交谈,不跟“陌生人”说话(Talk only to your immediate friends and not to strangers)。其含义是:如果两个软件实体无须直接通信,那么就不应当发生直接的相互调用,可以通过第三方转发该调用。其目的是降低类之间的耦合度,提高模块的相对独立性。
举例

image.png

合成复用原则

要求在软件复用时,要尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。

image.png

image.png