背景:
目前有一批控件类(Button,CheckBox,ListCtrl等),都是继承自Control类。
Control类提供一些通用Virtual方法,继承类按需求改写某些方法。
然后还有各个控件的管理类,比如管理Button的管理类ButtonCollection,负责更换皮肤、删除资源之类的需要集中处理的事务。现在客户端的调用就比较尴尬,需要定义控件类和管理控件类,比如CMyButton和CMyButtonCollection。需求:
我希望能有范型的设计把这些郁闷给消灭,然后客户端尽可能充分享受编程的乐趣!我用的WTL库做的开发,所以想尽可能的应用范型模式来设计开发PS:看着STL和LOKI把范型应用的那么优雅高效,羡慕啊~

解决方案 »

  1.   

    当然不是这么简单,我想用范型的模式,比如像Loki基于Policy思想。我是不是进入了过度设计的怪圈了?
      

  2.   


    既然各个具体控件类都派生自你的Control类,想必你在各个控件的公共操作上做了一定的抽象,但是具体情况是各个具体派生都有各自的不同特性,所有还是存在用法上的区别,做到很完美的泛型有些困难。我个人觉得原则是客户端代码使用方便就好,方便主要体现在使用流程和各个操作的概念清晰,避免冗余就行了。
      

  3.   

    to Jcily确实如你所说,Control类抽象了共有的接口
    但是我想在重新设计Collection和相关控件类(其实是贴图而已)的关系,以免在客户端调用的时候需要控件类和控件管理类,如CMyButton和CMyButtonCollection
      

  4.   

    觉得还是选择一种设计模式比较好。
    可以设计管理类的基类,对每个Control的子类设计一个管理类的子类。
    在管理类的基类有一个到Control类的指针,每个管理类的子类负责实例化自己的对象,保证每个控件管理器的子类生成对应的控件。
    可以参考Factrory 模式。
      

  5.   

    FACTORY METHOD(工厂方法)—对象创建型模式
      

  6.   

    目前没有用Factory模式,只是在特定类中固定生成控件类,然后Add进Collection进行管理
    比如
    CMyDialog
    {
    private:
        CMyButton[2] m_wndBtn;
        CMyButtonCollection m_btnCollection;
    };使用的时候
    btnCollection.Add(&m_wndBtn);
    现在,我想把Collection做成模板类,基于策略选择不同的控件类。虽然我都把所有控件类通用的行为都抽象了,但是某些控件还是有不同的行为。难点啊
      

  7.   

    class InterfaceBase
    {
    public:
    virtual IDispatch*  GetSelfObj() = 0;
    };
    template< class t>
    class cwnd : publc InterfaceBase
    {
    };
    class somewnd :publc cwnd
    {
    };//
    cwnd<somewnd > m_wnd;就这么个思路
      

  8.   

    想法不错,参考一下stl的源码,将Control类设计为模板类啊,反正其负责更换皮肤、删除资源之类的通用的
    与控件类型无关的操作。像CMyButtonCollection这样的一种控件类型,一个collection类的方式不好。
      

  9.   


    看你贴出的代码,你各个具体控件,在创建和销毁都由客户端代码在做,对应Collection做了一些其他事情,
    我觉得可以把各个控件的创建与销毁的实现细节代码也由Collection来做,而客户端代码只需要关心自己想要创建什么,而至于怎么创建由对应Collection来提供,返回给客户代码对应控件指针。
    另外,客户端还是需要知道(包含)各个具体控件类的,比如在操作特定控件时候。
    你想达到的目的似乎是在操作各个控件也做到泛型,这给设计本身增加一定的复杂性,你需要抽象操作层次,为客户代码构建一层操作上的统一的编程流程,而你再在这一层的实现中做具体的操作细节实现。从而让客户代码不亲自操作各个控件,只是发出请求或者命令。
    有没有必要再抽这么一层出来,完全根据实际情况来,若本身直接操作各个具体控件也很好理解,且各个具体控件的接口设计也达到了单一职责就没有太大必要。否则你抽象出来的一层概念在使用上流程更难理解,丢失了客户代码在使用上的灵活性,而只是编程代码少了几句,就不好了。
    设计时会有很多需要权衡的地方,这需要有丰富的经验。
      

  10.   

    对,我也想到了抽象接口
    把控件的通用行为抽象出来,按不同行为分类。
    比如,鼠标的移近移出,Down、Up为一类接口,而绘制为一类接口这样后,思路很清晰了,也方便以后扩展,但是感觉怪怪的。
      

  11.   

    css常用属性
      

  12.   

    用到泛型再用公共基类的话,就失去了泛型开销小的优点了。泛型的设计要点:把设计中的各方面特性都抽取出来,每个特性就是一个模板类型,特性的粒度可大可小。
    以你的需求作为例子,你现在需要一个集合管理类,第一步就是构造最粗的粒度: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;
      

  13.   

    嗯,最近看Generic Programming and the STL以及STL的一些历史,说到GP其实有一定程度的面向对象,STL之父之前在多种支持OOP的语言上尝试过(scheme, ada, java)实现和使用泛型算法,包括在C++完整引入模板之前他试图用单根继承来实现也非常困难,最后他的结论是完全的面向对象和GP不相容,或者说是正交的所以比较怀疑范型能承担GUI框架的设计作用,应该只能在容器和算法上面用一用