单一职责原则
单一职责原则的英文名称是Single Resposibility Principle,缩写 SRP。
SRP的定义是:
就一个类而言,应该仅有一个引起它变化的原因。简单来说,一个类中应该是一组相关性很高的函数、数据的封装。就像秦小波老师在《设计模式之禅》中说的:“这是一个备受争议却又极其重要的原则。只要你想和别人争执、怄气或者是吵架,这个原则是屡试不爽的”。因为单一职责的划分界限,并不是总是那么清晰,很多时候都是需要靠个人经验来界定。当然,最大的问题就是对职责的定义,什么是类的职责,以及怎么划分类的职责。
如果一个类承担的职责过多,就等于把这些职责耦合在一起,一个职责的变化可能会消弱或者抑制这个类完成其他职责的能力。
这种耦合会导致脆弱的设置,当变化发生时,设计会遭到意象不到的破坏。
开放-封闭原则
开闭原则的英文全称是Open Close Principle,缩写是OCP,它是Java世界里最基础的设计原则,它指导我们如何建立一个稳定的,灵活的系统。
定义:
软件中的对象(类、模块、函数等)
- 对于扩展是开放的
- 对于更改是封闭的
开放-封闭原则是面向对象设计的核心所在。遵循这个原则可以带来面向对象技术所声称的巨大好处,也就是可维护、可扩张、可复用、灵活性好。开发人员应该仅对程序中呈现出频繁变化的那些部分做出抽象,然而,对于应用程序中的每个部分都刻意地进行抽象同样不是一个好主意。拒绝不成熟的抽象和抽象本身一样重要。
里氏替换原则
里氏替换原则英文全称是Liskov Substitution Principle,缩写是LSP。
LSP的第一种定义是:
如果对每一个类型为S的对象O1,都有类型为T的对象O2,使得以T定义的所有程序P在所有的对象O1都代替成O2时,程序P的行为没有发生变化,那么类型S是类型T的子类型。
LSP的第二种定义是:
所有引用基类的地方必须能透明地使用其子类的对象。
简单的来说,一个软件实体如果使用的是一个父类的话,那么一定适用于其子类,而且它察觉不出来父类对象和子类对象的区别。也就是说,在软件里面,把父类都替换成它的子类,程序行为没有变化。简单的说,子类类型必须能够替换它们的父类型。
Question.
在面向对象设计时,一个是鸟类,一个是企鹅类,如果鸟是可以飞的,企鹅不会飞,那么企鹅是鸟吗?企鹅可以继承鸟这个类吗?
Answer:
面向对象设计中,子类拥有父类非private的行为和属性,鸟会飞,而企鹅不会飞。尽管在生物学上分类,企鹅是一种鸟,但是在编程世界里,企鹅不能以父类-鸟的身份出现。
因为前提说所有的鸟都能飞,而企鹅飞不了,所以不能继承鸟类。
依赖倒置原则
依赖倒置原则英文全称是:Dependence Inversion Principle,缩写是DIP。
关键点:
- 高层模块不应该依赖底层模块。两个都应该依赖抽象
- 抽象不应该依赖细节
- 细节应该依赖抽象
依赖倒置其实可以说是面向对象设计的标志,用哪种语言来编写程序不重要,如果编写时考虑的都是如何针对抽象编程而不是针对细节编程,即程序中所有的依赖关系都是终止于抽象类或者接口,那就是面向对象的设计,反之就是过程化的设计了。
依赖倒置原则在Java语言中的表现就是:模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类产生的。
接口隔离原则
接口隔离原则英文全称是:Interface Segregation Principle,缩写是ISP。
ISP的定义是:
客户端不应该依赖它不需要的接口。
另一种的定义是:
类间的依赖关系应该建立在最小的接口上。
接口隔离原则将非常庞大、臃肿的接口拆分成更小的和更具体的接口,这样客户将会只需要知道他们那感兴趣的方法。接口隔离原则的目的是系统解开耦合,从而容易重构、更改和重新部署。
Bob大叔(Robert C Martin)在21世纪早期将单一职责、开闭原则、里氏替换、接口隔离以及依赖倒置(也称依赖反转)5个原则,定义为SOLID原则,作为面向对象编程的5个基本原则。
迪米特原则
迪米特原则英文全称为Law of Demeter,缩写是LOD,也称为最少知识原则(Least Knowledge Principle)。
一个对象应该比对其他对象有最少的了解。简单的来说,一个类应该对自己需要耦合或调用的类知识知道得最少,类的内部结构如何实现与调用者或者依赖者没有关系,调用者或者依赖者只需要知道它需要的方法即可,其他的可一概不用管。类与类之间的关系越密切,耦合度越大,当一个类发生改变时,对另一个类的影响也越大。
代码:
售楼中心
package com.design.pattern.demeter;
import java.util.ArrayList;
import java.util.Random;
public class BuildingCenter {
private ArrayList<House> mHouses = new ArrayList<House>();
public BuildingCenter() {
}
/**
* 初始化房源
*/
public void addHouse() {
Random random = new Random();
for (int index = 0; index < 10; index++) {
mHouses.add(new House(random.nextInt(10) + "栋", random.nextInt(100) + 100, random.nextInt(20) + 100));
}
}
/**
* 卖房子
* @param location
* @param price
* @param area
* @return
*/
public House sellHouse(String location, int price, int area) {
for (House house : mHouses) {
if (isSuitHouse(location, price, area, house)) {
return house;
}
}
return null;
}
/**
* 是否合适
* @param location
* @param price
* @param area
* @param house
* @return
*/
private boolean isSuitHouse(String location, int price, int area, House house) {
if (house.getLocation().equals(location)) {
if (house.getPrice() <= price && house.getArea() >= area) {
return true;
}
}
return false;
}
}
房源
package com.design.pattern.demeter;
public class House {
private String location;
private int price;
private int area;
public House(String location, int price, int area) {
super();
this.location = location;
this.price = price;
this.area = area;
}
public String getLocation() {
return location;
}
public float getPrice() {
return price;
}
public float getArea() {
return area;
}
@Override
public String toString() {
return "House [location=" + location + ", price=" + price + ", area=" + area + "]";
}
}
买房人
package com.design.pattern.demeter;
public class Buyer {
/**
* 买房子
* @param location
* @param price
* @param area
* @param buildingCenter
*/
public void buyHouse(String location, int price, int area, BuildingCenter buildingCenter) {
House house = buildingCenter.sellHouse(location, price, area);
if (house != null) {
System.out.println("买到房子了:" + house.toString());
} else {
System.out.println("没有合适的房子!");
}
}
}
测试结果
package com.design.pattern.demeter;
public class TestResult {
public static void main(String[] args) {
BuildingCenter buildingCenter = new BuildingCenter();
buildingCenter.addHouse();
Buyer buyer = new Buyer();
buyer.buyHouse("6栋", 150, 90, buildingCenter);
}
}
Github地址:
DesignPatterns:https://github.com/EricWinner/DesignPatterns.git
有任何问题,欢迎指出.