Five Basic Principle 五项基本原则
五项基本原则
一个类由一个原因进行改变。 2. The Open/Closed Principle (OCP):开放-封闭原则 Software entities (classes,modules,functions,etc.) should be open for extension but closed for modification.软件实体(类、模块、方法等)应该对扩展开放对修改关闭。 3. The Dependency-Inversion Principle (DIP):依赖倒置原则 A. High-level modules should not depend on low-level modules. Both should depend on abstractions.高层模块不依赖于底层模块。应该依赖于抽象。 B. Abstractions should not depend upon details. Details should depend upon abstractions. 抽象不应该依赖于细节,细节应该依赖于抽象 4. The Liskov Substitution Principle (LSP):Liskov替换原则 Subtypes must be substitutable for their base types。子类型必须能够替换他们的父类型。 5. The Interface Segregation Principle (ISP):接口隔离原则 Clients should not be forced to depend on methods they do not use.不应该强制客户端使用他们不需要使用的方法。
SRP例1:调制解调器
调制解调器接口实际上包含了两个功能,连接(Dial,Hangup),数据交互(send,Recv),根据SRP原则,应该将其重构为两个接口,DataChanel与Connection,一个用于数据交互的功能,一个用于解调器连接的功能。
例2:领域逻辑与持久化在这个领域对象当中,即有业务逻辑的方法又有持久化的方法,不符合SRP原则。 基于SRP原则将其分离出两个类,一个用于领域逻辑,一个用于持久化。优点:在开发和维护阶段,使得关注点较少,便于开发以及维护。 OCP例1:绘图程序
譬如一个绘图程序,有一个RenderView主要去绘制各种图形。 switch(ShapeType){ case Circle: DrawCircle(); break; case Rectangle: DrawRectangle(); break; } 当我再添加一种图形三角形时,必须修改源代码,在switch语句中添加对三角形的代码处理。(重构中的一种坏味道:Switch)此时已经不符合OCP原则,对扩展是不开放的,需要修改源代码。 通过引入接口Shape,在渲染RenderView类中绘制ShapeList中的Shape,当我们再添加一种新图形的时候,简单继承Shape接口,实现Draw方法即可。对于现有的类,RenderView、Shape、ShapeList根本不必做修改。此时,完美的符合了OCP原则,对扩展新图像开放,对于修改现有的代码进行关闭。
DIP例1:层依赖在例子中UI层依赖于Logic层,Logic层依赖于persistence层,实际上违反了DIP原则,因为依赖于细节。在每层中定义所需要的接口,然后每层的细节都依赖于接口,然后下层根据接口进行实现,实际上每层依赖于抽象,而不依赖于细节。 对于每层的接口放置问题,可以根据情况而定。 ISP例1:取款机UI分离
在一个取款机的例子中,Deposit为存款,Withdrawal为取款,Transfer为转账。在UI接口中包含存款,取款,转账的接口。当在DepositTransaction中使RequestDepositAmt接口,但是对于其他的接口也具有可见性。在此处因为较为明显,但是在实际当中并不像例子中那么明显时候,就会造成选择疑惑,以及开发错误,此外在开发UI的实现时,实际上也具有了多种功能的实现,也不符合SRP原则。
通过对接口的分离,首先接口特别清晰,不会造成接口的误用,使得程序代码更清晰易懂。 LSPWhat is wanted here is something like the following substitution property: If for each object o1 of type Sthere is an object o2 of type T such that for all programs P defined in terms of T,the behavior of P isunchanged when o1 is substituted for o2 then S is a subtype of T. 例1:struct Point {double x,y;} public enum ShapeType {square,circle}; public class Shape { private ShapeType type; public Shape(ShapeType t){type = t;} public static void DrawShape(Shape s)//此处为static方法,不能使用多态 { if(s.type == ShapeType.square) (s as Square).Draw(); else if(s.type == ShapeType.circle) (s as Circle).Draw(); } } public class Circle : Shape { private Point center; private double radius; public Circle() : base(ShapeType.circle) {} public void Draw() {/* draws the circle */} } public class Square : Shape { private Point topLeft; private double side; public Square() : base(ShapeType.square) {} public void Draw() {/* draws the square */} 在Shape的DrawShape中首先已经破坏了OCP原则。当新添加一种图形时,必须修改DrawShape方法。其次在Circle和Square并不能覆盖Shape中的方法,此时Circle和Square并不能替换Shape。从这个例子可看出只要破坏了LSP原则,也就破坏了OCP原则。 例2:Square与Rectangle
void g(Rectangle r) { r.Width = 5; r.Height = 4; if(r.Area() != 20) throw new Exception("Bad area!"); }当g方法中传入Square的时候,其中的代码就会出错,也就是说Square不能替换成Rectangle。所以也就破坏了LSP原则。对于破坏LSP原则的典型代码,就是传入的父类型强转为特定的子类型,然后进行特殊处理。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |