Five Basic Principle 五项基本原则

五项基本原则

  1. The Single-Responsibility Principle (SRP):单一职责原则
A class should have only one reason to change。

一个类由一个原因进行改变。

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原则。


通过对接口的分离,首先接口特别清晰,不会造成接口的误用,使得程序代码更清晰易懂。

LSP

What is wanted here is something like the following substitution property: If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T.
对于每一个类型为S的对象o1,都有类型为T的o2,使得以T定义的所有程序P在所有对象o2都代换成o1时,程序p的行为没有变化,那么S是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原则的典型代码,就是传入的父类型强转为特定的子类型,然后进行特殊处理。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值