用State模式建立向导的实践。。。

简介:
向导就是类似于安装软件时,一大堆下一步的那个窗体。每一个上一步下一步意味着窗体上的控件需要改变,相关的按钮的功能等也需要改变。在制作一个向导时,最初设计中,我用的enum来表示每一个步骤。比如:
switch(stepEnum) 

case StepEnum.FirstStep: 
    //some work 
    break; 
case StepEnum.SecondStep: 
    //some work 
    break: 
//... 
default: 
    //... 
}
这样的设计,使得整个代码中充斥着大量的switch...case语句,并且使得每个步骤涉及到的控件布局,逻辑处理等代码混在一起。很是丑陋,无法忍受。于是我想用试着用state模式来除掉这些坏掉的味道。
State模式用[GOF]的话来说,使允许一个对象在其内部状态改变时改变它的行为。我定义一个抽象的步骤类来取代原有的枚举结构,各步骤继承与这个抽象类。其定义如下:
public abstract class InitWizardStepState 

        public abstract void AddControlToContainer(Control container); 
        public abstract bool CouldGoToNext(); 
        public abstract InitWizardStepState GoToNextStep(); 
        public abstract InitWizardStepState GoToPreStep(); 
        public abstract bool IsFirstStep { get;} 
        public abstract bool IsLastStep { get;} 
}
 
通过这样的设计,将每一个步骤的逻辑判断和UI设计都封装在了StepState中。避免了在主窗口中使用枚举类来判断各个操作。简化了主窗口的代码,实现了相关的隔离,除掉了坏掉的味道。同时,利用单件模式,降低反复上一步,下一步付出的代价。基本达到了目的。
但是实践就是实践,没有经典问题那么的纯粹,有些问题很是折磨人。比如步骤转换的控制是由谁控制。步骤转换并不是一个简单的由1-->2-->3-->...的过程。而根据用户输入和选择的不同,可能存在1-->3-->...这样的路径,也可能有1-->2(1)-->3-->...这样的路径。设计中是将状态的转移控制封装在了InitWizardStepState类中(使用GoToNextStep和GoToPreStep来控制)。比如:在1步骤是获取需要转移和需要删除的文件列表,2步骤处理转移文件,3步骤处理删除文件。如果1步骤中,用户并没有输入转移文件,就可以跳过2直接进到3中。直接封装在步骤中可以使得这种处理可以在内部完成。但我越来越觉得这不是一个良好的决定。因为并不符合开闭原则。如果我需要建立一个新的向导,这个向导的次序和相关处理与老步骤不同。我如果还想使用原先的步骤类,我必须修改里面的逻辑,而并不是利用继承建立新的步骤即可。说明这个设计不够良好。
导致这个问题出现的原因,我想是因为在步骤转换是存在着数据的转移.比如在1步骤中获得了某个路径,在2步骤中需要获得这个路径,就将路径需要由步骤1传个步骤2。这其实就与state模式的应用范围产生了偏差。在state模式中,要求作为state的对象可以不依赖于其他对象而独立变化。所以我一直不确定我所谓的state是不是真正的state。
在下一步工作中,想继续改造上面的结构。即把各个步骤所需的(输入和输出的数据)放在一个类中,作为一个context存在。比如:以上面的转移文件和删除文件为例,建立context如下:
public class Context 

        public string[] deleteFileList; 
        public string[] moveFileList; 
}
 
然后将决定上下步骤的部分从StepState中提取出来。放在主窗口中完成。进一步降低了步骤类之间的耦合。同时增加各步骤类于Context之间的联系。比如:
将public abstract void AddControlToContainer(Control container);
改为public abstract void AddControlToContainer(Control container,Context context);
这样可以更好的保持可扩展性和可重用性。









本文转自 duguguiyu 51CTO博客,原文链接:http://blog.51cto.com/duguguiyu/363383,如需转载请自行联系原作者
目录
相关文章
|
7月前
|
供应链
如何取消 SAP ALE 中已经配置的跨系统主数据验证
如何取消 SAP ALE 中已经配置的跨系统主数据验证
41 0
|
11月前
|
网络协议
【解决方案 十八】连接已重置怎么办
【解决方案 十八】连接已重置怎么办
846 0
|
SQL 数据库
OushuDB 用户指南书籍定义创建和管理模式之创建模式
OushuDB 用户指南书籍定义创建和管理模式之创建模式
39 0
|
存储 移动开发 JavaScript
vue-router先hash模式部署项目,然后开启histroy模式 ,引发的几个问题以及histroy模式的开启方式、优点
前言: vue路由有一个HTML5 History 模式,这个模式要在路由里面另外开启的,很多人在刚使用路由的时候之前不知道这个模式,所以并没有启用,然后就把项目部署上去了,因为这个模式还是有挺多优点的,最后还是会开启这个模式。 然而因为之前使用hash模式再改为histroy模式还是有些问题的,我已经踩过坑了,然后把这几个问题写出来。有需要的朋友可以做一下参考,喜欢的可以点波赞,或者关注一下,希望可以帮到大家。 本文首发于我的个人blog:obkoro1.com 开启history模式: 如果不开启的话,路由默认是hash模式,开启这个模式前端的工作也很简单,如下:
214 0
vue-router先hash模式部署项目,然后开启histroy模式 ,引发的几个问题以及histroy模式的开启方式、优点
|
Java Linux 数据安全/隐私保护
将ABAP On-Premises系统连接到中央检查系统以进行自定义代码迁移
将ABAP On-Premises系统连接到中央检查系统以进行自定义代码迁移
124 0
将ABAP On-Premises系统连接到中央检查系统以进行自定义代码迁移
|
Java Android开发
CC框架实践(1):实现登录成功再进入目标界面功能
用CC来AOP地实现登录成功后再跳转到目标界面功能
1514 0