OOP六大原则
OOP名词解析
Object 对象
Oriented 面向
Programming 编程
说明:面向对象编程,是指面向对象程序设计,是一种计算机编程架构。OOP 的一条基本原则是计算机程序是由单个能够起到子程序作用的单元或对象组合而成。
面向对象编程技术的关键性观念是它将数据及对数据的操作行为放在一起,作为一个相互依存、不可分割的整体——对象。对于相同类型的对象进行分类、抽象后,得出共同的特征而形成了类。面向对象编程就是定义这些类。
目前有六条原则
- 单一职责原则
- 开闭原则
- 里氏替换原则
- 依赖倒置原则
- 接口隔离原则
- 迪米特原则
单一职责原则
定义
就一个类而言,应该仅有一个引起它变化的原因。应该只有一个职责。
说明
每一个职责都是变化的一个轴线,如果一个类有一个以上的职责,这些职责就耦合在了一起。这会导致脆弱的设计。当一个职责发生变化时,可能会影响其它的职责。另外,多个职责耦合在一起,会影响复用性。例如:要实现逻辑和界面的分离。
开闭原则
定义
类,模块,函数等等对于扩展是开放的,对于修改是封闭的
说明
在面向对象编程领域中,开闭原则规定“软件中的对象(类,模块,函数等等)应该对于扩展是开放的,但是对于修改是封闭的,这意味着一个实体是允许在不改变它的源代码的前提下变更它的行为。该特性在产品化的环境中是特别有价值的,在这种环境中,改变源代码需要代码审查,单元测试以及诸如此类的用以确保产品使用质量的过程。遵循这种原则的代码在扩展时并不发生改变,因此无需上述的过程。
里氏替换原则
定义
派生类(子类)对象可以在程式中代替其基类(超类)对象。子类可以扩展父类的功能,但不能改变父类原有的功能
说明
里氏替换原则的关键点在于不能覆盖父类的非抽象方法。父类中凡是已经实现好的方法,实际上是在设定一系列的规范和契约,虽然它不强制要求所有的子类必须遵从这些规范,但是如果子类对这些非抽象方法任意修改,就会对整个继承体系造成破坏。而里氏替换原则就是表达了这一层含义。
-
子类可以实现父类的抽象方法,但是不能覆盖父类的非抽象方法
在我们做系统设计时,经常会设计接口或抽象类,然后由子类来实现抽象方法,这里使用的其实就是里氏替换原则。子类可以实现父类的抽象方法很好理解,事实上,子类也必须完全实现父类的抽象方法,哪怕写一个空方法,否则会编译报错。
里氏替换原则的关键点在于不能覆盖父类的非抽象方法。父类中凡是已经实现好的方法,实际上是在设定一系列的规范和契约,虽然它不强制要求所有的子类必须遵从这些规范,但是如果子类对这些非抽象方法任意修改,就会对整个继承体系造成破坏。而里氏替换原则就是表达了这一层含义。
-
子类中可以增加自己特有的方法
在继承父类属性和方法的同时,每个子类也都可以有自己的个性,在父类的基础上扩展自己的功能。前面其实已经提到,当功能扩展时,子类尽量不要重写父类的方法,而是另写一个方法
-
当子类覆盖或实现父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松
依赖倒置原则
定义
设计代码结构时,高层模块不应该依赖低层模块,二者都应该依赖其抽象
说明
抽象不应该依赖细节,细节应该依赖抽象。通过依赖倒置,可以减少类与类之间的耦合性,提高系统的稳定性,提高代码的可读性和可维护性,并且能够降低修改程序所造成的风险。
理解
上层负责整体逻辑,下层负责具体的实现,上层逻辑模块不直接依赖与下层功能模块,而是依赖于接口,接口约束了下层功能模块需要实现哪些功能
示例
主体流程功能说明
本次示例是一个图片管理功能,图片管理功能需要下载模块,但是只有在使用的时候才知道使用的是http还是ftp来下载文件,所以图片管理功能要求在使用时先设置下载功能适配器,图片管理功能类中下载功能适配器使用接口来存放,下载适配器需要实现此接口
下载管理器代码
public class ImageManger {
private IDownloadAdapter mDownloadAdapter;
public void setDownloadAdapter(IDownloadAdapter iDownloadAdapter) {
mDownloadAdapter = iDownloadAdapter;
}
public void startDownload(String imageUrl, String savePath, DownloadCallback downloadCallback) throws Exception {
if (mDownloadAdapter==null){
throw new Exception("请设置下载器后在下载图片");
}
mDownloadAdapter.startDownload(imageUrl, savePath, downloadCallback);
}
}
下载功能适配器接口代码
public interface IDownloadAdapter {
void startDownload(String downloadUrl, String savePath, DownloadCallback downloadCallback);
}
因为网络请求是一个异步的,结果使用一个接口来回调
结果回调接口代码
public interface DownloadCallback {
void success(String downloadUrl, String savePath);
void fail(String downloadUrl, int errorCode, String errorMsg);
}
http方式下载文件功能适配器代码
public class HttpDownloadAdapter implements IDownloadAdapter {
@Override
public void startDownload(String downloadUrl, String savePath, DownloadCallback downloadCallback) {
//...伪代码下载成功
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
downloadCallback.success(downloadUrl, savePath);
}
}).start();
}
}
ftp方式下载文件功能适配器代码
public class FTPDownloadAdapter implements IDownloadAdapter {
@Override
public void startDownload(String downloadUrl, String savePath, DownloadCallback downloadCallback) {
//...伪代码下载成功
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
downloadCallback.success(downloadUrl, savePath);
}
}).start();
}
}
最终使用时代码片段
ImageManger imageManger = new ImageManger();
//上层不决定使用哪种方式实现下载文件功能,将选择权提供给使用的地方,仅使用接口来约束下载方式需要实现哪些功能
//imageManger.setDownloadAdapter(new FTPDownloadAdapter()); //FTP方式下载文件
imageManger.setDownloadAdapter(new HttpDownloadAdapter()); //http方式下载文件
try {
imageManger.startDownload("图片下载地址", "图片保存地址", new DownloadCallback() {
@Override
public void success(String downloadUrl, String savePath) {
}
@Override
public void fail(String downloadUrl, int errorCode, String errorMsg) {
}
});
} catch (Exception e) {
e.printStackTrace();
}
接口隔离原则
定义
客户端不应该依赖它不需要的接口。一个类对另一个类的依赖应该建立在最小的接口上。
说明
接口应保持最小单元,定义时应遵守单一职责原则,防止实现的类或接口污染.如有类需要定制接口可以单独创建一个定制接口.继承多个最小单元接口来达到目的
迪米特原则
定义
迪米特法则(Law of Demeter)又叫作最少知识原则(The Least Knowledge Principle),一个类对于其他类知道的越少越好,就是说一个对象应当对其他对象有尽可能少的了解,只和朋友通信,不和陌生人说话。英文简写为: LOD。
说明
一个类只和有直接接触类交流,拿上方依赖倒置原则的示例代码做说明,上层图片管理模块只和下载适配器接口有直接接触,图片管理模块只需要知道下载模块能下载并且返回什么接口就行了,不关心具体实现类(http和ftp下载适配器)具体是怎么实现的