文章目录
面向对象设计原则概述
单一职责原则
开闭原则
里氏代换原则
面向对象设计原则概述
软件的可维护性(Maintainability)和可复用性(Reusability)是两个非常重要的用于衡量软件质量的属性,软件的可维护性是指软件能够被理解、改正、适应及拓展的难易程度,软件的可复用性是指软件能够被重复使用的难易程度。
面向对象的设计目标之一在于支持可维护性复用,一方面需要实现设计方案或者源代码的复用,另一方面确保系统能够易于拓展与修改,具备良好的可维护性。
面向对象设计原则也是后续学习设计模式的基础,某一个设计模式都符合某一个或者多个面向对象的设计原则。
单一职责原则
概述
单一职责原则是最简单的面向对象的设计原则,它用于控制类的粒度大小,其定义如下:一个对象应该只包含单一的职责,并且该职责被单一地封装在一个类中。另一种定义是:就一个类而言,应该仅有一个引起它变化的原因。
在软件系统中,一个类(大到模块,小到方法)承担的职责越多,它被复用的可能性就越小,而且一个类承担的职责过多,相当于将这些职责耦合在一起,当其中一个职责变化时可能会影响其他职责的运作,因此要将这些职责进行分离,将不同的职责封装在不同的类中,即将不同的变化原因封装在不同的类中,如果多个职责总是同时发生改变则可将它们封装在同一类中。
单一职责原则是实现高内聚、低耦合的指导方针,它是最简单但又是最难运用的原则。
示例
这个设计原则最简单也很容易理解,故省略示例代码。
开闭原则
概述
开闭原则是面向对象的可复用设计的第一块基石,它是最重要的面向对象的设计原则。
开闭原则的定义是:软件实体应当对拓展开放,对修改关闭。通俗地来说,开闭原则就是指在软件实体尽量在不修改原有代码的情况下进行拓展。
为了满足开闭原则,需要对系统进行抽象化的设计,抽象化是开闭原则的关键。在很多面向对象的语言中都提供了接口、抽象类等机制,可以通过它们来定义系统的抽象层,再通过具体类来进行拓展。如果有新的业务需求,只需要增加新的具体类来实现新的业务功能,不需要变动抽象层,这样就达到了在不修改原来代码的前提下拓展系统的功能,达到开闭原则的要求。
示例
代码
AbstractSkin.java
package com.Demo.Principles.开闭原则;
/**
* 抽象皮肤类
*/
public abstract class AbstractSkin {
//用于显示
public abstract void display();
}
DefaultSkin.java
package com.Demo.Principles.开闭原则;
public class DefaultSkin extends AbstractSkin{
@Override
public void display() {
System.out.println("这是默认皮肤...");
}
}
HeimaSkin.java
package com.Demo.Principles.开闭原则;
public class HeimaSkin extends AbstractSkin{
@Override
public void display() {
System.out.println("这是黑马皮肤...");
}
}
SogoInput.java
该类实现聚合关系,将抽象皮肤类与具体的皮肤类进行聚合,后者与前者属于部分与整体的关系。
package com.Demo.Principles.开闭原则;
/**
* 聚合关系:搜狗输入法类
*/
public class SogoInput {
private AbstractSkin skin;
//传入皮肤类
public void setSkin(AbstractSkin skin){
this.skin=skin;
}
//调用当前皮肤的显示输出的方法
public void display(){
skin.display();
}
}
测试已有皮肤对象
此时,如果有了一个新的业务需求,要求增加一个王者皮肤,只需要增加一个新的具体皮肤类继承抽象的皮肤类,实现其所有方法,达到了“开闭原则”。
KingSkin.java
和前面的具体皮肤类写法一致,进行业务的拓展,无需修改原有的任何代码
package com.Demo.Principles.开闭原则;
public class KingSkin extends AbstractSkin{
@Override
public void display() {
System.out.println("这是王者皮肤...");
}
}
测试新增加的皮肤
这就是开闭原则的简单运用,不修改原代码实现业务功能的拓展,对拓展开放,对修改关闭。
里氏代换原则
概述
里氏代换原则是指:所有引用基类(父类)的地方必须能够透明地使用其子类的对象
通俗理解就是,子类可以拓展父类的功能,但不能改变父类原有的功能。
换句话说,子类继承父类时,除了添加新的方法完成新的业务功能之外,尽量不要去重写父类的方法,否则会导致整个继承体系的可复用性变差。
里氏代换原则表明:
- 在软件中将一个基类对象替换成它的子类对象,程序将不会产生任何错误和异常
- 反之则不成立,如果一个软件实体使用的是一个子类对象,那么它不一定能使用基类对象
因此,我们在软件设计时:
- 在程序中尽量使用基类类型来定义对象,因为在使用基类对象的地方一定可以使用其子类对象;而在运行时再确定其子类类型,用子类对象来替换父类对象
- 在使用该原则时,应该将基类,即父类设计成抽象类或者接口,让子类继承父类或者实现父类的接口,并实现在父类中声明的方法,在运行时子类实例替换父类实例,可以很方便的拓展系统的功能,无需修改原有的子类的代码,增加新的功能可以通过增加一个新的子类来实现
END.