咱们知道软件开发的需求老是不完整的,错误的,容易让人产生误解的,并且需求一直在变化,它主要表如今如下几个方面:用户对需求的见解,可能在于开发人员讨论以及看到软件新的可能性后发生变化;随着对问题的熟悉,开发人员对问题领域的见解也会变化;不是需求在变,而是人们对需求的理解再变化。编程
咱们应该采用何种方法去应对需求变化呢?首先,在方法论层面咱们应该采用敏捷开发;其次,在代码层面,使用OOD(Object-Oriented Design,面向对象设计),它的根本原则:面向接口编程;多用组合,而不是继承;发现变化,封装变化。但如何让设计知足这个原则呢?咱们的先辈们总结出了5条设计原则,俗称SOLID原则,这就是本期咱们要介绍的详细内容。bash
Robert C. Martin 大师对于单一职责原则有这样一个定义:一个类应该仅有一个引发它变化的缘由,而这个引发变化的缘由就是职责。那么职责是什么东西呢?先来讲说咱们人类的职责。做为项目经理,个人职责是:项目计划、需求管理、项目成本控制、项目时间控制等,我须要处理不少事情,同时,这些事紧密相关的。对应到面向对象设计领域,一个类的职责应该包含多个相关的功能。好比说用户控制类中通常包含了新增用户、删除用户、修改用户等相关功能。微信
开闭原则就是说对扩展开发,对修改封闭。看到这里,咱们不由会问:新增功能还能够不用修改代码呀? 这是如何作到的呀?实际上开闭原则指的是提供者增长新的功能,而使用者不须要修改代码,而且增长的新功能不能是一个全新的功能,而是原有功能的替代实现。为了帮助你们理解,我举一个具体的例子。目前购物车有添加商品、计算价格两个功能,而商品有香蕉、苹果两种。Java代码以下:测试
public interface Item{
public String getName();
public float getPrice();
}
public class Apple implements Item {
public String getName() {
return "Apple";
}
public float getPrice() {
return 5.0f;
}
}
class Orange implements Item{
public String getName() {
return "Orange";
}
public float getunitPrice() {
return 6.0f;
}
}
public class ShopCar {
List<Item> items = new ArrayList<Item>();
public void addItem(Item item) {
items.add(item);
}
public float calculateTotalPrice() {
float total = 0.0f;
for (Item i : items) {
total += i.getPrice();
}
return total;
}
}
复制代码
咱们注意到当新增一个香蕉类,ShopCar类不用修改,这是由于香蕉类是原有功能的替代实现,而不是一个全新的功能,若是购物车中新增商品价格变化这一全新功能,则须要修改ShopCar类。ui
LSP替换原则指的是:子类型可以彻底替换父类。它最经典的例子就是长方形和正方形。咱们知道正方形是一种特殊的长方形,可是在面向对象设计领域,正方形并不能做为长方形的子类。缘由在于设置正方形的长或宽时,同时设置了它的宽或长,那么,正方形的面积等于最后一次设定的长或宽的平方,而不是长乘以宽。具体Java代码以下:this
// 长方形
public class Rectangle {
protected int width;
protected int height;
public void setWidth(int width){
this.width = width;
}
public void setHeight(int height){
this.height = height;
}
public int area(){
return width*height;
}
}
// 正方形
public class Squrare extends Rectangle{
public void setWidth(int width){
this.width = width;
this.height = height;
}
public void setHeight(int height){
this.width = width;
this.height = height;
}
}
// 测试类
public class Test{
public static void main(String[] args){
Rectangle rectangle = new Rectangle();
rectangle.setWidth(4);
rectangle.setHeight(5);
// 正确
assert( rectangle.getArea() == 20);
rectangle = new Square();
rectangle.setWidth(4);
rectangle.setHeight(5);
// 错误,此时正方形面积是25
assert( rectangle.getArea() == 20);
}
}
复制代码
判断一个子类是否知足LSP替换原则,咱们能够像上面这个例子那样,在测试类中用子类来替换父类。若是测试可以经过,则说明符合LSP原则,不然就说明不符合LSP原则。spa
虽然咱们要求软件开发人员都要遵循SRP,可是不少状况下类是没有知足SRP原则的,这个时候就须要用到接口隔离原则。ISP原则指的是客户端不该该被强迫去依赖它们并不须要的接口。也就是说,调用方调用的不须要是一个大而全的接口,而是一个小而精的接口。设计
DIP包含两层意思:1. 高层模块不该该直接依赖低层模块,二者都应该依赖抽象层;2. 抽象不能依赖细节,细节必须依赖抽象。这里模块是个广义概念,能够是系统、子系统、子模块,甚至是类。而依赖包含多层意思:高层模块调用底层模块的方法,底层模块继承或实现抽象层。3d
欢迎关注微信公众号:木可大大,全部文章都将同步在公众号上。code