OEA中的AutoUI重构(1) - Command自动生成

 OEA框架的核心之一是AutoUI,其职责是面向领域模型及UI元模型进行生成统一的界面。

    在本次的迭代开发中,需要对命令按钮的生成方式进行一些定制。由于原来并没有为这样的需求留有特别的扩展点,加之原来的生成代码是过程式的代码、且也变得比较冗长,所以我们决定对这一部分的代码进行重构。


原来的模式

    历史代码中,为某一实体类生成命令按钮的流程是这样的:

  1. 找到实体类可用的所有命令按钮元数据。
  2. 对它们进行过滤,依靠权限、版本的客户化元信息等。
  3. 构造几个生成控件的List容器,分别是:itemsInToolbar,itemsInContextMenu,itemsInGroup。
  4. 遍历所有的命令按钮,根据其对应的元数据,分别生成相应的控件(按钮、菜单等),然后添加到容器中。
    其中,还有对某些命令的特殊生成处理。例如,为了给命令生成一个附带的文本框,特别添加了IParameterizedCommand接口,实现这个接口的命令,则会调用它自己的控件生成方法来生成控件。应用开发时,扩展的命令需要实现自己的控件生成方案。
  5. 对同一容器中的命令控件进行排序和一些其它的操作。
  6. 把容器中的每一项添加到界面中。

    由于功能是一点一点加进来的,整个代码是过程化的,冗长而不易维护。扩展起来也比较不便。原来只能实现IParameterizedCommand接口并自行生成文本控件,要在总体上控制整个生成流程也只能修改上面的流程中对应的代码,最终只会导致代码膨胀得无法维护。


草稿

    重构不是重做。所以我们不是全部推翻重做,而只是把流程进行优化,并进行职责划分,用适当的对象来承担对应的职责,让类与类之间的协作来完成整个流程。

    首先,整个流程中比较重要的是控件的生成和分组。在进行OO设计时,先要对这部分进行抽象。先看看原来的生成的ToolBar的一张图:

OEA中的AutoUI重构(1) - Command自动生成

(样式没有做,不好看,哈哈。)图中,主要有三类:分组下拉、带文本的按钮、一般的按钮,当然还应该包含右键菜单中的菜单项。再加上这些迭代的新的样式,画出了下面的草稿:

OEA中的AutoUI重构(1) - Command自动生成

图中,主要的GroupGenerator的职责是对一组命令进行控件生成,一般情况下一组命令可以生成SplitButtons、GroupTextbox。当一个组中只有一个命令时,它就变为了特殊的ItemGenerator,当个命令可以生成:文本按钮、一般按钮、菜单等。而如何把所有的命令进行分组并生成GroupGenerator,就是GroupingAlgorithm的职责。


详细设计

    (以下内容中涉及具体的OEA的类的职责,用于项目组内沟通,不关心的朋友可以直接跳过细节描述。)

    最后的具体设计方案中,分为以下几下主要的部分:

OEA中的AutoUI重构(1) - Command自动生成 

  1. CommandAutoUIContext:这是对整个生成环境的抽象。
  2. CommandAutoUI:这里面包含了整个生成的流程。
  3. Generators:这里面包含了所有的框架内置的命令组生成方案。
  4. GroupAlgorithms:这里用于把命令进行分组,并为命令组分配生成器。

以下,详细说明每个部分的设计:

CommandAutoUIContext

OEA中的AutoUI重构(1) - Command自动生成

CommandAutoUIContext 表示生成流程的上下文对象。它比较简单,只是包含了整个生成流程中需要用到的参数,这些参数包含:需要生成命令的实体的元数据信息、可用的ToolBar对象、可用的菜单、所有实体包含的命令、命令要用到的参数。

CommandAutoUIComponent 类表示整个生成流程中的可用的组件,这些组件都可以直接获取上下文对象中的内容。

CommandAutoUI

OEA中的AutoUI重构(1) - Command自动生成

这里包含整个生成的流程所用到的核心对象:

CommandGroup 表示一个命令组,其中有组名。

GroupGenerator 是一个命令组的生成器,这里为它分配了以下职责:为命令组生成控件、把控件添加到上下文中。

GeneratableGroup 整合了上述两个对象,表示一个可生我生成的命令组。

GroupAlgorithm 表示某个命令的抽象的分组算法。注意,它只负责对某个命令进行分组。

GroupOperation 作为分组操作的执行者,调用分组算法对所有命令进行分组。它负责对所有的命令进行分组。

以上对象作为生成流程的核心对象,被CommandAutoUIManager进行组织并完成最终的界面生成:

OEA中的AutoUI重构(1) - Command自动生成

GroupGenerators

OEA中的AutoUI重构(1) - Command自动生成

图中列出了框架内置的可能用到的所有生成器。当然了,要扩展界面生成时,只需要编写新的子类就行了。

具体的内容在前面的“草稿”已经有所描述,在此不再赘述。

GroupAlgorithms

OEA中的AutoUI重构(1) - Command自动生成

GroupAlgorithm 是策略模式的应用。

框架中内置三个分组算法:

DropDownListAlgorithm 表示把某一个命令分组到下拉组中。

DefaultAlgorithm 表示默认的一个命令一组的分组算法。

GenericItemAlgorithm 表示指定新的生成方式的分组算法。(添加这个类,是因为扩展时,80%以上情况只是为命令更换一种生成显示界面而已。)

 

整个流程用对象描述如下:

OEA中的AutoUI重构(1) - Command自动生成


其它相关改动

    IParametrizedCommand 由原来的只支持 String 的 附加文本框命令变为更抽象的“需要参数的命令”。界面生成的控件在用户“填入”数据时,会组装出其所需要的参数,然后对它进行回调:

1
2
3
4
5
6
7
8
9
10
11
/// <summary>
/// 一种需要其它参数才能执行的命令。
/// </summary>
public interface IParametrizedCommand : ICommand
{
    /// <summary>
    /// 界面中输入的参数改变时,会通知这个Command参数值改变了。
    /// </summary>
    /// <param name="value"></param>
    void NotifyParameterChanged(object value);
}

 


总结

    这里再总结一个小的经验:

在开发过程中,为了简化代码,曾尝试使用设置属性的方式来设计构造函数的必要参数。但是属性设置并不是必需的,一旦忘记,则会需要调试才能找到问题所在,得不偿失。也就是说:

  • 不要以为类少就认为自己能记住其中的设置约定。最好是让编译器提醒你。 :)
  • 不要因为简化代码而去尝试违反一些好的设计规范。否则,不但可能写出不易调试的代码,而且影响后人的阅读。

本文转自BloodyAngel博客园博客,原文链接:http://www.cnblogs.com/zgynhqf/archive/2010/12/10/1902449.html,如需转载请自行联系原作者
上一篇:第三方模拟器连接Android studio


下一篇:Redis安装与应用