背景:
目前有一批控件类(Button,CheckBox,ListCtrl等),都是继承自Control类。
Control类提供一些通用Virtual方法,继承类按需求改写某些方法。
然后还有各个控件的管理类,比如管理Button的管理类ButtonCollection,负责更换皮肤、删除资源之类的需要集中处理的事务。现在客户端的调用就比较尴尬,需要定义控件类和管理控件类,比如CMyButton和CMyButtonCollection。需求:
我希望能有范型的设计把这些郁闷给消灭,然后客户端尽可能充分享受编程的乐趣!我用的WTL库做的开发,所以想尽可能的应用范型模式来设计开发PS:看着STL和LOKI把范型应用的那么优雅高效,羡慕啊~
目前有一批控件类(Button,CheckBox,ListCtrl等),都是继承自Control类。
Control类提供一些通用Virtual方法,继承类按需求改写某些方法。
然后还有各个控件的管理类,比如管理Button的管理类ButtonCollection,负责更换皮肤、删除资源之类的需要集中处理的事务。现在客户端的调用就比较尴尬,需要定义控件类和管理控件类,比如CMyButton和CMyButtonCollection。需求:
我希望能有范型的设计把这些郁闷给消灭,然后客户端尽可能充分享受编程的乐趣!我用的WTL库做的开发,所以想尽可能的应用范型模式来设计开发PS:看着STL和LOKI把范型应用的那么优雅高效,羡慕啊~
既然各个具体控件类都派生自你的Control类,想必你在各个控件的公共操作上做了一定的抽象,但是具体情况是各个具体派生都有各自的不同特性,所有还是存在用法上的区别,做到很完美的泛型有些困难。我个人觉得原则是客户端代码使用方便就好,方便主要体现在使用流程和各个操作的概念清晰,避免冗余就行了。
但是我想在重新设计Collection和相关控件类(其实是贴图而已)的关系,以免在客户端调用的时候需要控件类和控件管理类,如CMyButton和CMyButtonCollection
可以设计管理类的基类,对每个Control的子类设计一个管理类的子类。
在管理类的基类有一个到Control类的指针,每个管理类的子类负责实例化自己的对象,保证每个控件管理器的子类生成对应的控件。
可以参考Factrory 模式。
比如
CMyDialog
{
private:
CMyButton[2] m_wndBtn;
CMyButtonCollection m_btnCollection;
};使用的时候
btnCollection.Add(&m_wndBtn);
现在,我想把Collection做成模板类,基于策略选择不同的控件类。虽然我都把所有控件类通用的行为都抽象了,但是某些控件还是有不同的行为。难点啊
{
public:
virtual IDispatch* GetSelfObj() = 0;
};
template< class t>
class cwnd : publc InterfaceBase
{
};
class somewnd :publc cwnd
{
};//
cwnd<somewnd > m_wnd;就这么个思路
与控件类型无关的操作。像CMyButtonCollection这样的一种控件类型,一个collection类的方式不好。
看你贴出的代码,你各个具体控件,在创建和销毁都由客户端代码在做,对应Collection做了一些其他事情,
我觉得可以把各个控件的创建与销毁的实现细节代码也由Collection来做,而客户端代码只需要关心自己想要创建什么,而至于怎么创建由对应Collection来提供,返回给客户代码对应控件指针。
另外,客户端还是需要知道(包含)各个具体控件类的,比如在操作特定控件时候。
你想达到的目的似乎是在操作各个控件也做到泛型,这给设计本身增加一定的复杂性,你需要抽象操作层次,为客户代码构建一层操作上的统一的编程流程,而你再在这一层的实现中做具体的操作细节实现。从而让客户代码不亲自操作各个控件,只是发出请求或者命令。
有没有必要再抽这么一层出来,完全根据实际情况来,若本身直接操作各个具体控件也很好理解,且各个具体控件的接口设计也达到了单一职责就没有太大必要。否则你抽象出来的一层概念在使用上流程更难理解,丢失了客户代码在使用上的灵活性,而只是编程代码少了几句,就不好了。
设计时会有很多需要权衡的地方,这需要有丰富的经验。
把控件的通用行为抽象出来,按不同行为分类。
比如,鼠标的移近移出,Down、Up为一类接口,而绘制为一类接口这样后,思路很清晰了,也方便以后扩展,但是感觉怪怪的。
以你的需求作为例子,你现在需要一个集合管理类,第一步就是构造最粗的粒度:template<class TControl /*=CMyButton*/ >
class ControlManagerT
{ ... };接下来你会发现不同控件的使用有些差别(这里假设控件不是从同一个公共基类派生的,否则没必要搞泛型),导致上面的管理模板很难写代码,这时就需要把粒度细化,方法就是把差别的地方再次封装成一个模板类型,假设消息处理机制不同,就为每种控件设计一个消息接受者类(或函数等):template<class TControl, class TMessageReceiver>
class ControlManagerT
{ ... };第三步,这里还能继续优化,例如某些控件的消息接受者可以合并,那么可以把 TMessageReceiver 也做成一个模板类,封装一些通用的处理,针对少量控件定义特化模板类,例如:template<class TControl>
class MessageReceiverT { ... };template<>
class MessageReceiverT<CMyButton> { ... }; // CMyButton 特化类
... // 可能还有其它特化类// 管理类就可以这样定义:
template<class TControl, class TMessageReceiver=MessageReceiverT<TControl> >
class ControlManagerT { ... }上述细化过程可以一直持续下去,直到满足需求为止!等你做下去之后,你就会发现STL/ATL之流都是这样设计的。只不过它们是通用的,所以粒度非常精细,但你自己的实际应用中是不需要这么精细的。最后的用法:
ControlManagerT<CMyButton> m_btnCollection;