欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

state 和 statement

程序员文章站 2022-03-05 17:21:01
...

1. Strategy Pattern and State Pattern

(1) Strategy Pattern (i)定义:

定义了算法族,把变化的各个部分封装起来,使得算法可以相互替换并独立于使用该算法的客户。

(ii)结构图: Strategy Pattern/State Pattern - chenxuezhen_1 - 风中飘絮

(iii)意图:封装变化以便类型在运行时根据需要选择合适的算法。这样提高了代码的复用度,也使程序更改更方便。

(iv)用到的OO原则:封装变化;对扩展开放,对修改关闭;针对接口编程而不是实现编程;多用组合少用继承。

(v)例子: 假设我们要完成公司员工这个类的操作,算法如下:

Employees {

string height;

string weight;

string diploma;

public string Description() {

string desc=””; desc += “Heighht:”+height+”;”;

desc += “Weighht:”+weight+”;”;

desc += “Diploma:”+diploma+”;”;

return desc;

}

public decimal GetWage() {

decimal wage if(temp) {

wage = 10*hours;

}

if(accountant) {

wage = 2000+ bonus;

} if(manager) {

wage 5000+bonus+ earning*5%;

}

……

return wage;

}

} 这里,我们假设Employees这个类有两个函数,一个用于个人情况描述的,一个用于计算工资的。个人描述是不变的,而工资的算法则因人而异。这样如果员工的种类改变了,增加或减少都要对类里面的函数进行修改。这种情况下我们就可以用Strategy Pattern来处理了。 首先把变化的部分也就是GetWage这个函数抽象出来成为一个接口或者抽象类: Interface Wage { GetWage(); } 然后根据具体需要加入Wage的子类实现GetWage(); TempWage:Wage { GetWage() { wage = 10*hours; } } AccountantWage:Wage { GetWage() { wage = 2000+ bonus; } } ManagerWage:Wage { GetWage() { wage 5000+bonus+ earning*5%; } } 这样以后就可以在Employees中声明一个Wage接口,把工资的计算委托给Wage接口中的函数来实现,Employees就变成: Employees { Wage wage; public Employees(Wage wage) { this.wage = wage; } string height; string weight; string diploma; public string Description() { string desc=””; desc += “Heighht:”+height+”;”; desc += “Weighht:”+weight+”;”; desc += “Diploma:”+diploma+”;”; return desc; } public decimal GetWage() { wage.GetWage(); } } 这样之后如果程序中要算Manager的工资就可以这样来做了: Manager :Employees() { public Manager() { wage = new ManagerWage();//这里决定用具体哪个工资计算法 } } 这时,主函数中用到的GetWage将是wage 5000+bonus+ earning*5%; Static void main() { Manager manager = new Manager(); Manager.GetWage(); Employees tempemployees = new Employees (new TempWage()); Tempemployees.GetWage();//这里用的将是Temp的工资计算法 } 例子中用策略模式的好处是:如果以后有新的工资计算法,我们只需要加入一个新的Wage子类,而不需要对Employees这个类做任何的改动。这样做还可以复用代码,如果另外一个类有类似的计算和某个工资计算一样,我们也可以直接用Wage这个接口,而不需要加入新的类或接口。 (2) State Pattern (i) 定义:允许对象在内部状态改变的时候改变其行为,使得对象看起来好像改变了它的类。 (ii) 结构图: Strategy Pattern/State Pattern - chenxuezhen_1 - 风中飘絮 (iii) 意图:把与对象状态相关的行为放入状态组成的类中,使对象状态的行为能够随着状态的改变而该变。 (iv) 用到的OO原则:和Strategy Pattern一样。 (v) 例子: 这里我们用TCP连接来举例,TCP连接有三个状态:Open,Lisening, Close,初步实现如下: TCPConnection { string open_state =”open”; string closed_state = “closed”; string listening_state = “listening”; string state = closed_state; public string Open { if(state == open_state) { return “TCP has been opened”; } if(state == closed_state) { state = open_state; return “open successfully” } if(state == listening_state) { return “TCP is listening”; } } public string Close { if(state == open_state) { state =closed_state; return “Closed Successfully”; } if(state == closed_state) { return “TCP has been closed” } if(state == listening_state) { state =closed_state; return “Closed Successfully”; } } public string Listening { if(state == open_state) { state =listening_state; return "Listen Successfully”; } if(state == closed_state) { return “TCP has been closed” } if(state == listening_state) { return “TCP is listening”; } } } 这样,如果我们每加一个State的话,要为每个函数都加一条实现语句,不仅麻烦还很容易出现bug.于是我们就想到了State Pattern。 实现一个State接口: State { Open(); Close(); Listening(); } 实现各个具体状态类: OpenState:State { TCPConnection tcp;//用于记录状态 Open() { return “TCP has been opened”; } Close() { tcp.state = CloseState; return “Close Succefully”; } Listening() { tcp.state = ListenState; return “Listen Succefully”; } } CloseState:State { TCPConnection tcp;//用于记录状态 Close() { return “TCP has been closed”; } Open() { tcp.state = OpenState; return “Open Succefully”; } Listening() { return “TCP has been closed”; } } ListenState:State { TCPConnection tcp;//用于记录状态 Open() { return “TCP is listening”; } Close() { tcp.state = CloseState; return “Close Succefully”; } Listening() { return “TCP has been closed”; } } 这样改了之后TCPConnection就可以写成: TCPConnection { State OpenState; State CloseState; State ListinState State state = CloseState ; state.Open(); state.Close(); state.Listening(); } 使用State Pattern后如果加入新的状态,我们只需要加入新状态的一个State子类就可以了。 (3) Strategy Pattern和State Pattern 异同点: (i) 同点:两种模式的结构图一样,做法都是用接口或者抽象类来封装变化的方法。一般来说在类中有许多判断语句的时候就可以考虑使用这两种模式。(当然模式使用时基于变化的,如果判断语句的条件是定死的,那么不用设计模式也没有问题) (ii) 不同点:意图不一样:State Pattern中很显著的特点就是有状态和行为,并且行为随着状态的改变而改变,相当于判断语句中的条件是一种种状态。State Pattern中实现的状态子类中是有耦合的。而Strategy Pattern,我个人认为判断语句中的条件是类别,不同的类型实现的操作不一样,这样就可以把操作抽象出来。抽象出来的操作子类之间是解耦的。