State模式在客户端软件中的应用(2)客户端应用

- UID
- 1072456
|

State模式在客户端软件中的应用(2)客户端应用
2. 客户端应用本模式的目标是分离客户端软件中的变化部分与不变部分,以使得变化的部分可独立于不变的部分,有利于扩充新的功能,也有利于维护。
在项目中,对于客户端GUI的重用有两种方式。
- 方式1适用于:相同数据集合,不同操作模式;此时,在GUI中定义客户端数据处理验证逻辑,不同的状态对象封装了不同的操作模式;
- 方式2适用于:不同数据集合,相同操作模式;此时,在状态对象中定义客户端数据处理验证逻辑,不同的状态对象封装了不同的数据集合操作。
2.1 类型1: Read-Only & Normal2.1.1 动机
客户端GUI接受用户输入,经过数据有效性验证,然后将数据传输到服务端,服务端检查业务逻辑有效性,保存数据;但是在特定情况下(比如数据已经存在、且只能经历一次输入),依据客户端GUI所操作数据的状态,业务逻辑要求数据为只读,即客户端只具有显示数据的功能,并不能改变服务器上的数据。
一般地,编程实现时,会在GUI程序中加入判断数据是否应该为只读的逻辑判断语句。如果针对相同的数据集合(Model),有多个客户端GUI(View),就需要在每个程序中加入该判断。如此降低了程序的可维护性,决定数据是否为只读的这样一个业务逻辑将分散在程序中多处,不易维护,在业务逻辑发生改变时,易造成不一致。
我们可以将变化部分(在Normal和Read-Only状态下不同的部分)从GUI中抽取出来,分别用不同的类来表示,这样,当GUI的状态发生改变时,只需要改变其对状态对象的引用即可,状态相关操作委托给状态对象去完成。
2.1.2 适用性
本类型适用环境:相同数据集合,不同操作模式。即特定的GUI根据操作上下文环境,改变其响应模式,根据数据是否可编辑,分为两种状态Read-Only State、 Normal State。
2.1.3 结构(图2)
图2 相同数据集合,不同操作模式 点击查看大图
2.1.4 参与者
- ClientStateChangeable:客户端GUI提供给State对象的操作接口,使得State对象可以访问GUI的成员,以完成该状态相关操作;
- getChangeableComponents():返回在状态转换为Read-Only时,不可编辑的控件Collection;
- saveChangeToServer():在可编辑状态时,将客户端数据保存到服务端。
- AClientGUI:完成图1中的Context功能,即其状态要进行改变的客户端GUI;维护ClientState的一个实例(state);
- init():将this引用作为参数,调用state.setComponents(this) 以设置可变控件的初始状态;
- okButtonActionPerformed(e:ActionEvent):用户完成操作后,本方法可作为 "OK"按钮控件的ActionListener方法,调用state.action(this) 以完成本操作。
- ClientState:State接口,封装与客户端GUI某个特定状态相关的行为;
- setComponents(gui:ClientStateChangeable):设置参数gui指定的客户端GUI的控件状态;
- action(gui:ClientStateChangeable):完成数据保存功能。
- ClientNormalState:可编辑状态子类,实现ClientState接口;
- setComponents(gui:ClientStateChangeable):调用参数gui指定的客户端GUI的getChangeableComponents()获取控件Collection,然后遍历设置各控件状态为可编辑;
- action(gui:ClientStateChangeable):调用参数gui指定的客户端GUI的saveChangeToServer()完成数据保存功能。
- ClientReadOnlyState:只读状态子类,实现ClientState接口;
- setComponents(gui:ClientStateChangeable):调用参数gui指定的客户端GUI的getChangeableComponents()获取控件Collection,然后遍历设置各控件状态为ReadOnly;
- action(gui:ClientStateChangeable):空方法,本状态下无数据变化,无须保存。
2.1.5 代码示例
ClientStateChangeable接口:
1
2
3
4
5
6
7
8
9
10
11
12
| public interface ClientStateChangeable {
/**
* To get all changeable components in the GUI object.
* @return Collection contains Component objects.
*/
Collection getChageableComponents();
/**
* To save data to server.
*/
void saveChangeToServer();
}
|
AClientGUI类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| public class AClientGUI extends JPanel implements ClientStateChangeable{
//…
private ClientState state = null;
public DesignStep1View(ClientState state){
//…
this.state = state;
this.state.setComponents(this);
}
private void okButton_actionPerformed(ActionEvent e){
state.action(this); //save data
}
public Collection getChageableComponents() {
Collection dataComponents = new ArrayList();
dataComponents.add(jComboBoxESEPattern);
//…
return dataComponents;
}
public void saveChangeToServer() {
//…
}
}
|
ClientState接口:
public interface ClientState { /** * To set components' state in the GUI. * @param gui a GUI object which implements StateChangeable interface. */ void setComponents(ClientStateChangeable gui); /** * when user click OK-Button in a GUI, the GUI will call this method. * @param gui a GUI object which implements StateChangeable interface. */ void action(ClientStateChangeable gui);} |
|
|
|
|
|