最近一直在一个培训公司做着极为无聊的培训,所以一直都没有时间上网。今天突然发现这里可以上无线,嘿嘿,就上来继续把这个文章完成。
上次说到了设计原则中的单一职责原则,今天时间比较紧,我就继续往下写,也不知道能写几个。
现在来说一下设计模式的核心,开放封闭原则(OCP原则)。开放封闭原则我想每一个人都可以从字面上很容易地理解他的意思,就是说对扩展开放,对修改封闭。一个优秀的软件是可以无限扩展的,而且是不需要修改类的内部结构的(当然这是指的理想状况,实际上,无论设计多么优异的软件,一旦扩展,总是要对类内部进行修改的)。
上次我记得我说过,设计模式,也是OO的目标,无非是两个,可重用和可扩展。我们来从这两个方面来分析OCP,我们先说可扩展,这个我想我不用多说了,都说过对扩展开放的,当然是可扩展了。可重用等我先举个例子再来分析下这个。
在这个,我举个我前两天做的一个小型计算器。我们先来分析一下这个小型计算器,我把一个小型计算器的按钮抽象为以下几个功能:数字键,二元运算符,一元运算符,修饰符(比如说小数点),等于号。然后我把这几个功能分别封装成一个自定义控件。现在来说下二元运算符,代码如下:
1
public partial class ButtonOperateTwo : UserControl2

{3
private TextBox textBoxResult = null;4
public ButtonOperateTwo()5

{6
InitializeComponent();7
}8
public ButtonOperateTwo(string text, TextBox textBoxResult)9

{10
InitializeComponent();11
this.buttonOperate.Text = text;12
this.textBoxResult = textBoxResult;13
}14

15
private void buttonOperate_Click(object sender, EventArgs e)16

{17
SaveNumber1(this.textBoxResult.Text);18
this.textBoxResult.Text = "0";19
SaveOperate(this.buttonOperate.Text);20
}21

22
private void SaveNumber1(string num1)23

{24
Number.Number1 = this.textBoxResult.Text;25
}26
private void SaveOperate(string operate)27

{28
Number.Operate = operate;29
}30
}1
public struct Number2

{3
public static string Number1 = "0";4
public static string Number2 = "0";5
public static string Operate = "+";6
}在这里,我来简单地说下我这段程序的思路。我之前没有做过任何Winform程序,没有找到缓存,因此我声明了一个结构体来存储所需要的数字和操作符。然后当点击二元运算符后,我就把textBoxResult的Text传入到Number1中,然后同时也把操作符来暂存到结构体中。这样,以后无论有什么二元运算符,我们都不需要再写那么多重复的代码,而只需要简单的调用这个二元运算符就可以了,而不需要任何修改。
因此,我们很常用的自定义控件,就是开放封闭原则的最好体现。
基本上所有设计模式的目的都是开放封闭。在这里,我来简单地提下一个很好地体现了开放封闭的设计模式——工厂模式。
工厂模式是创建者模式的一种,用于解决对象的创建问题。我的这个计算器应用的就是工厂模式。
我这里不大方便画图,就用语言来描述一下吧。
我创建两个类库,分别为运算类库和工厂类库。在运算类库中有一个基类OperateBase,在他的下面有两个子类分别为一元运算子类和二元运算子类。而这个子类下又分别有着具体的运算子类。在工厂类库中有两个基类,分别是二元运算工厂类和一元运算工厂类。而每个基类下又有着具体的运算工厂类,分别用于返回运算类。我们来简单地看一些示例代码:
1
public abstract class OperateBase //运算基类2

{3
public abstract string GetResult();4
}5
public abstract class OperateOne:OperateBase //一元运算基类6

{7
public double Number18

{9
get;10
set;11
}12
}13
public class OperateSqrt:OperateOne //开方运算14

{15
public override string GetResult()16

{17
double result;18
result = Math.Sqrt(Number1);19
return result.ToString();20
}21
}22
public abstract class OperateFatoryOne //一元运算工厂基类23

{24
protected OperateOne thisOperate = null;25
public abstract OperateOne GetOperate();26
}27
public class OperateFactorySqrt : OperateFatoryOne //开方运算工厂类28

{29
public override OperateOne GetOperate()30

{31
return new OperateSqrt();32
}33
}34
private string ReturnResult() //客户端调用方法35

{36
try37

{38
OperateFactory.OperateFatoryOne thisOperateFactory = null;39
switch (this.button1.Text)40

{41
case "+/-":42
thisOperateFactory = new OperateFactory.OperateFactoryReverse();43
break;44
case "sqrt":45
thisOperateFactory = new OperateFactory.OperateFactorySqrt();46
break;47
case "1/x":48
thisOperateFactory = new OperateFactory.OperateFactoryCountDown();49
break;50
case "%":51
thisOperateFactory = new OperateFactory.OperateFactoryPercent();52
break;53
}54
OperatingSystem.Operate.OperateOne thisOperate = thisOperateFactory.GetOperate();55
thisOperate.Number1 = Convert.ToDouble(this.thisTextBox.Text);56

57
string result = thisOperate.GetResult();58
return result;59
}60
catch 61

{62
string result = "您的输入有误";63
return result;64
}65
66
}67

68

于是,我们就可以自由地添加一元运算符了,当添加时,我们只需要添加一个运算子类,添加一个工厂子类,然后在客户端的switch的case中添加一个条件。当然,这里就是我说的,不存在完全的开放封闭,无论设计多么优异的软件。即使在这里用抽象工厂+反射,也仍然需要加以修改,我没那样设计的原因是因为那样的设计对效率实在有点.....
最后,对以上的文字做个总结。
开放封闭原则是整个设计模式的核心,依我的理解,所有的设计模式,包括所有的设计原则都是围绕着OCP展开的。一个优秀的软件设计师可以忘记所有的设计模式,甚至都可以忘记所有的设计原则,但是开放封闭原则必须永记心中。
好了,就写到这。然后说个昨天开《建筑的永恒之道》,上面有这样一句话,什么才能成就建筑的永恒之道,学会方法,然后忘掉他。













