LSP:Liskov Substitution Principle Liskov 替换原则
Subtypes must be substitutable for their base types.子类必须能够替换基类
例:正方形IS-A矩形,因此我们会设计成正方形继承至矩形,然而假如有以下代码:
public Rectangle IncreaseHeight(Rectangle r) { while(r.getHeight()<r.getWidth())) { r.setHeight(r.getHeight()++) } return r; }
就会有错误出现。
应用:在具体实现在,要求应该针对 “接口”或“抽象基类”进行编程,充分利用面向对象的多态特性,让实现同一接口或抽象基类的子对象可以互相取代而不影响到程序的其他部分。
反例:.NET基类库中的ReadOnlyCollection类,ReadOnlyCollection<T>实现了ICollection<T>接口,但这接口中的Add()、Clear()方法对于只读集合是无意义的。
ISP:Interface Segregation Principle 接口隔离原则
No client should be forced to depend on methods it does not use
不应该强迫一个软件组件依赖于它们不用的方法
- 要避免设计出一个“包罗万有”的大接口,而应该将定义的功能从逻辑上进行分组,将其切分为多个小接口。
- 各个类按需实现接口
例:IRepository接口既有“命令”(Save,Update)又有“查询”(Find,GetById)功能
public interface IRepository { public void Save(MyDataItem item); public void Update(MyDataItem item); public void Delete(int ItemId); public MyDataItem GetById(int ItemId); public List<MyDataItem> Find(Predicate<MyDataItem> pred); }
可以拆分为两个接口:
public interface IMutableRepository { public void Save(MyDataItem item); public void Update(MyDataItem item); public void Delete(int ItemId); } public interface IQueryableRepository { public MyDataItem GetById(int ItemId); public List<MyDataItem> Find(Predicate<MyDataItem> pred); }
DIP:Dependency Inversion Principle 依赖倒置原则
- High-level modules should not depend on low-level modules. Both should depend on abstractions.
- Abstractions should not depend upon details. Details should depend upon abstractions.
- 高层模块不应该依赖于低层模块,两者都应该依赖于抽象。
- 抽象不应该依赖于细节,细节应该依赖于抽象。
依赖注入:类本身不直接实例化它所依赖的类的对象,而是由外界动态了将其“注入(inject)"