面向对象的设计六大原则

面向对象的设计原则

单一职责原则 - Single Responsibility Principle

从字面上去理解这个意思,就是一个类只承担单一的职责。
其定义

是有且只有一个类引起类的变化

比如,有一个类

public class OmnipotentPerson {
    public void java(){}
    public void python(){}
    public void golang(){}
}

我们可以看到这个万能人的类当中,存在三种方法,也承担着三个职责。假如项目现在只需要Java的功能,但是部署的时候需要整个类都一起部署。之后我变更了python模块,整个类也需要一起重新部署。
从此可见,一个类如果承担的职责过多,就会把职责耦合在一起。
优点

类的复杂度降低,每一个类的职责都会有明确的定义,可读性提高。
维护或者变更的风险降低

开放封闭原则 - Open Closed Principle

其定义

一个软件实体如类、模块和函数应该对扩展开放,对修改关闭

也就是说对应一个软件实体,理应通过扩展来来实现功能的变化,而不是进行修改原有的代码。
在项目从一开始的确立到最后维护的时候,项目的需求可能存在着不断的变化。而我们面对这些需求,应该通过扩展对应的模块进行满足需求,而不是大篇幅的修改原有的代码。
引用 https://blog.csdn.net/xiechao198609150053/article/details/51594162 的一句话

对扩展开放,对修改封闭,这两个特征似乎就是相互矛盾的. 通常观念来讲,扩展不就是修改源代码吗?怎么可能在不改动源代码的情况下去更改它的行为呢?
答案就是抽象(Interface 和 抽象基类).实现OCP的核心思想就是对抽象编程. 让类依赖于固定的抽象,对修改就是封闭的; 而通过面向对象的继承和多态机制,通过覆写方法改变固有行为,实现新的扩展方法,对于扩展就是开放的.

遵循开放封闭原则最好的方法就是抽象。
把一个类抽象成一个接口,每一块的业务就会成为一个一个的实现类,到时候的修改需求,就会变为扩展对应的模块。
成功的降低耦合度,每一个实现类之间互不影响。

里氏替换原则 - Liskov Subsitution Principle

其定义

如果对每一个类型为T1的对象o1,都有类型为T2的对象o2,使得以T1定义的所有程序P在所有对象o1都替换成o2的时候,程序P的行为都没有发生变化,那么类型T2是类型T1的子类型。

通俗的讲,只要能使用父类的地方,就可以使用子类;但是反过来却不行。
1、子类可以实现父类的抽象方法,但是不能覆盖父类的非抽象方法。
2、子类可以有自己的个性,可以有自己的属性和方法。
3、子类覆盖或重载父类的方法时输入参数可以被放大。
4、子类覆盖或重载父类的方法时输出结果可以被缩小,也就是说返回值要小于或等于父类的方法返回值。

依赖倒置原则 - Dependence Inversion Principle

其定义

高层模块不应该依赖底层模块,两者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象;

接口就可以理解为抽象,接口的具体的实现类就是细节。那么接口必定不能依赖于它的实现类,同时接口的多个抽象类之间也不能是相互直接依赖的。

比如一个牛奶类

public class Milk {
    public String taste() {
        return "原味";
    }
}
public class Produce{
	public void produceMilk(Milk milk) {
        System.out.println("牛奶" + milk.taste());
    }
}

那么接下来,这个厂家添加了新的口味,猕猴桃味。我们怎么进行修改,是直接在produce里面重新进行修改?那么影响的类就有两个类了,之后进行新增口味,就一直需要对produce进行修改,显然不符合我们的需求。
那么我们不如将牛奶抽象为一个接口,每一种口味作为他的实现类

public interface Milk {
    public String taste();
}
public class OriginalMilk implements Milk {
    public String taste() {
        return "原味";
    }
}
public class KiwifruitMilk implements Milk {
    public String taste() {
        return "猕猴桃味";
    }
}
public class Produce{
	public void produceMilk(Milk milk) {
        System.out.println("牛奶" + milk.taste());
    }
}

这样子就很好的降低了耦合性和后续维护的成本,提高了系统的稳定性。

接口隔离原则 - Interface Segregation Principle

其定义

客户端不应该依赖它不需要的接口

通俗的讲就是需要什么接口就提供什么接口,把不需要的接口进行剔除。这就需要对接口进行细化,保证接口的纯洁性。
举例子,上面的万能人的类抽象成一个接口

public interface OmnipotentPerson {
    public void java();
    public void python();
    public void golang();
}

但是事实上,并不是每个人都是万能人,所以不一定需要所有的接口。但是接口的实现类,必须要实现所有的方法,所以就导致一些实现类多了一些无用的方法。
我们可以根据接口的不同特性进行细分,保证了接口的纯洁性,也进一步提高了代码的灵活性和稳定性。

迪米特原则 - Law of Demeter

其定义

一个对象应该对其他对象有最少的了解

通俗的讲,一个类对于其他的类的了解,即引用或者调用越多,那么类于类之间的关系就会更加的密切,耦合度越大。那么我们知道耦合度越大,当我更改其中一个类的成本就会更好。
所以我们设计的核心原则就是:低耦合,高内聚

参考了《设计模式之禅》和大佬的文章
https://www.cnblogs.com/yeya/p/10655760.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值