面向对象的设计原则

201 阅读4分钟

本文已参与「新人创作礼」活动, 一起开启掘金创作之路。

开闭原则

开闭原则是最基础也是最重要的一个原则 开闭原则的定义很简单就是对修改关闭,对扩展打开

举个例子:我每天计划学5个小时,对于学5个小时是不需要修改的,但是我学完了5个小时,当然可以去干别的事情

一个工程被很多地方引用到,要是修改了这个类,不免会出现想不到的错误,所有有了新需求应该扩展,而不是去修改。

遵循开闭原则可以带来很大的好处。

/**
 * 获取价格的接口
 *
 * @author yang
 * @date 2022/1/1
 */
public interface Money {

    double getMoney(int price, int count);
}

/**
 * 正常价的类
 *
 * @author yang
 * @date 2022/1/1
 */
public class DangDang implements Money {

    @Override
    public double getMoney(int price, int count) {
        return price * count;
    }

}

这是一个书城类平时都是原价买,要是双十一搞活动打折那岂不是要修改这个类,不符合开闭原则

那就应该扩展一个折扣类出来

/**
 * 打折的类
 *
 * @author yang
 * @date 2022/1/1
 */
public class discountDangDang extends DangDang{

    public double discount; // 折扣

    public discountDangDang(double discount) {
       this.discount = discount;
    }

    @Override
    public double getMoney(int price, int count) {

        return  price * count * discount;
    }

    public static void main(String[] args) {

        Money dangDang = new DangDang();
        Money discountDangDang = new discountDangDang(0.7);
        System.out.println("原价是:"+ dangDang.getMoney(10, 1)+"元 优惠后是"+ discountDangDang.getMoney(10,1) + "元");
		// 原价是:10.0元 优惠后是7.0元
    }	

}

依赖倒置原则

对于依赖倒置原则的定义:高层模块不应该依赖于底层模块,二者都应该依赖就抽象

  • 细节依赖就抽象,抽象不依赖于细节
  • 面向接口编程,尽量不要针对实现编程
public class Yang {

    public void readJava() {
        System.out.println("读java的书");
    }

    public void readCpp() {
        System.out.println("读c++的书");
    }
}
public class Test {

    public static void main(String[] args) {

        Yang y = new Yang();
        y.readCpp();
        y.readJava();
    }
}

这样写Test是高层完全依赖于Yang也就是底层模块,这些完全违背了依赖倒置原则,改造一下

public class Yang {

    public void readBook(Book book) {
        book.readBook();
    }
}

interface Book {

    void readBook();
}

class CppBook implements Book {

    @Override
    public void readBook() {
        System.out.println("阅读c++的数");
    }
}

class JavaBook implements Book {

    @Override
    public void readBook() {
        System.out.println("阅读java的书");
    }
}

class Test {

    public static void main(String[] args) {

        Yang y = new Yang();
        y.readBook(new CppBook());
        y.readBook(new JavaBook());
    }
}

Pasted image 20220101193734.png 这样Test高层和Yang底层这个类就解耦合了看什么书由Test自己选择,Yang和具体的实现也没有耦合,只于Book这个接口有耦合, 这就是面向接口编程

抽象远远比细节要稳定的多

单一职责原则

对于单一职责原则的定义:不要存在多与一个导致类更改的原因

实现遵循的规则

  • 一个类、接口、方法只负责一个功能

这个比较好理解就不写代码了,真实的开发中,类可以看情况来用单一职责,不然会出现类过多,对于接口和方法就最好采用单一职责了, 维护起来也很方便,代码的逻辑也非常清晰

接口隔离原则

对于接口隔离原则的定义:用多个专门的接口,而不使用单一的接口,客户端不应该依赖他不需要的接口

实现遵循的规则

  • 一个类对一个类的依赖应该建立在最小的接口上

和单一职责原则差不多

迪米特原则

定义:一个对象应该对其他对象保持最少的了解,也叫最少知道原则

实现遵循的规则

  • 强调只对朋友交流,不和陌生人接触
  • 朋友就是成员变量,方法中的输入和输出变量

里氏替换原则

定义比较复杂简单来说就是子类必须能替换父类

举个例子:鸟是一个类,企鹅也是一种鸟,如果让企鹅去继承鸟,那就错了,企鹅根本不会飞, 我们在他们基础之上在抽象就一个动物就可以了,让企鹅去继承动物。

当子类替换掉父类,功能不受影响,父类才真正被复用

组合复用原则

定义:尽量使用组合或者聚合,而不是继承关系来达到复用

总结:这么多设计原则都是在找出抽象,减低耦合提高内聚