posts - 18, comments - 317, trackbacks - 0, articles - 0
  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理

剖析SharpDevelopCommand模式的应用    

SharpDevelop是一个非常优秀的开源项目,其中有一些思想非常出色的,如插件结构,服务设计,设计模式的应用,UI与行为的抽离,以及可插入式的设计结构, 其中有些设计思想我已经应用到我以前开发过的一些项目中。由于我的文笔不好及工作太忙,所以一直没有写什么心得之类的笔记。现在有点时间,也来记录一下我的分析随笔,先来分析一下SharpDevelop中模式的应用,至于其非常优秀的插件结构,博客园已有兄弟作过分析了。

           在剖析Command模式之前,先来看一下.NET Framework中的菜单及工具栏处理存在的一些缺点:

1.            无法自动同步更新菜单项与工具项的状态以及相关的行为及特性,需要手动去处理两个事件,从而造成了相同的两个操作需要两次处理,也就造成了需要手动地同时维护多份相同的操作;

2.            无法重用菜单项这部分的功能,因为在dotnet中菜单项的单击需要集成在UI中;

3.            无法很好地扩展,如需要增加或删除菜单项,则需要更改原有的代码及UI部分的设计,从而违反了OCP(开闭)原则。按照OCP原则,当扩展相关的功能时,不应该修改原始的代码,而应该扩展该代码;

4.            无法将相关的消息当作原子状态处理,试想一下,如果一个系统不仅通过菜单、工具栏来操作用户接口,也可通过命令(如Visual Studio就可以通过输入命令而执行相关的操作)来执行,如果不将相关的操作抽象出来的话,维护这个操作的成本太大。并且如果想实现更进一步的控制比如精确到原子状态的权限控制,则很难实现。

我们可以运用Command模式,将菜单项相应的操作抽象出来,定义一个命令接口ICommand,此接口仅具有Run方法,可以作为任何命令的基接口。但是由于菜单还具有一些其它的特性,如是否可见,是否可用,文本,需要执行此菜单项的宿主,所以再定义了一个IMenuCommand接口继承此接口,加入了一些新的特性,并定义了一个实现IMenuCommand接口的抽象基类MenuCommand,其它类可以派生此类。由于我自已修改了SharpDevelop中的一些设计,所以可能有些与原版的不一样。

 
          ICommand
接口:是一个最基本的接口,代表一个动作的行为;

IMenuCommand接口:派生于ICommand接口,作为菜单项或工具项所实现的行为及特性来使用;

IStatusUpdate接口:描述一个能够更新状态的接口,当对象需要更新状态时将调用此接口,如菜单项需要动态地更新EnableVisible特性;

MenuCommand抽象基类:实现了IMenuCommand接口,任何菜单命令可以从此继承;

CustomCommandBarItem:继承于CommandBar组件的CommandBarButton类,类似于菜单项或工具项,实现了IStatusUpdate接口,以根据IMenuCommand接口的VisibleEnabled属性的改变而相应地更新其Enabled,Visible属性;

CustomCommandBarMenu:继承于CommandBar组件的CommandBarMenu类,类似于菜单条。           
    当我们在客户端需要创建命令时,只需写相关的类继承于MenuCommand         
        

           在这里使用了另外一个开源组件CommandBarCustomCommandBarItem类的构造函数通过传入一个IMenuCommand类的实例与IMenuCommand关联起来,将单击事件(OnClick方法)委托给ICommand接口的Run方法来执行,其Update方法用于更新状态。CustomCommandBarMenu类中的OnDropDown方法用于当打开菜单条时通过调用IStatusUpdateUpdate方法自动更新所有菜单项的状态。

           SharpDevelop处理所有插件的菜单中,此处的设计是支持的基础。

          

           如果更进一步,可以在SharpDevelop中加入类似于Visual Studio的“命令窗口”;如果是一个ERP系统或MIS系统,可以将权限控制写在IMenuCommand中的Enabled中,在执行Run方法之前先检测Enabled,如果Enabledfalse则禁止执行,我先前写过一个权限框架,通过AttributeReflect技术来实现权限的自动控制。

           Reference:

1.            吕震宇的设计模式系列文章

2.            GoFDesign Pattern

Feedback

#1楼  回复 引用 查看   

2005-01-20 12:05 by idior      
明晚开会,收一下邮件

#2楼  回复 引用 查看   

2005-01-20 13:38 by wayfarer      
你用的画uml的软件是和idior一样的吧?感觉不太好!

很少看到你的文章哦,希望从这篇开始,多写一点:)

Command模式的应用还是很多的。以后我也该多看一些开源项目,结合一些例子谈模式,方才言之有物。

#3楼[楼主]  回复 引用 查看   

2005-01-20 14:49 by jeseeqing      
@Wayfarer,的確不好看,是使用Together自動生成的。

因為文筆不好,所以很少寫文章。不過我會努力的,Thanks。

#4楼  回复 引用   

2005-06-25 22:13 by silas
能提供源码吗?

#5楼  回复 引用   

2005-06-27 09:43 by jeseeqing
http://www.icsharpcode.net/網站中可以找到下載

#6楼  回复 引用 查看   

2006-02-07 21:14 by 勤能补拙      
请大哥指教一下,在SharpDevelop中如何动态地刷新菜单的状态?
QQ:307331145

#7楼[楼主]  回复 引用 查看   

2006-02-08 09:26 by jeseeqing      
在SharpDevelop中其菜单使用的是CommandBar开源组件。

在SharpDevelop组件通过继承CommandBar中的CommandBarItem类,并且重写了其OnDropDown方法,以在此方法中通过检测其下属的子Item是否实现了IStatusUpdate接口,如果实现了,则通过调用IStatusUpdate的方法来更新菜单的状态。这样每当一个菜单项被DropDown时将会自动更新其状态,当然要想更新必须实现IStatusUpdate接口。

详情请见SharpDevelop的代码

#8楼  回复 引用   

2006-07-16 16:49 by vsweaver[未注册用户]
想要一份。
vsweaver@163.com

#9楼  回复 引用   

2008-06-27 10:41 by jdsuchen[未注册用户]
--引用--------------------------------------------------
勤能补拙: 请大哥指教一下,在SharpDevelop中如何动态地刷新菜单的状态?
QQ:307331145
--------------------------------------------------------

用了个很偷懒的办法
Application.Idle 事件 中调用 WorkbenchSingleton.Workbench.UpdateToolbars();

#10楼  回复 引用   

2008-06-27 10:43 by jdsuchen[未注册用户]
--引用--------------------------------------------------
jdsuchen: --引用--------------------------------------------------
勤能补拙: 请大哥指教一下,在SharpDevelop中如何动态地刷新菜单的状态?
QQ:307331145
--------------------------------------------------------

用了个很偷懒的办法
Application.Idle 事件 中调用 WorkbenchSingleton.Workbench.UpdateToolbars();
--------------------------------------------------------
错了那是toolbar,菜单是每次下拉的时候都会刷新状态

#11楼  回复 引用   

2008-07-28 17:22 by 方伟[未注册用户]
都是高手,本人是业余编程爱好者,能否帮一下忙,最近刚看到sharpdevelop的源码,对其中的TextEditorControl比较感兴趣,现在它的基本功能:复制、粘贴、全选,高亮度文本配置刚掌握,但还缺少一个主要功能,就是查询和替换功能,在sharpdevelop源代码中好像是以插件的形式编程的,我现在很想使用TextEditorControl这个控件,不知如何编程实现查询功能。