(转载)Visitor模式---实现家人行为 http://hi.baidu.com/huangrg/blog/item/aa9e46c7feaeebdfd100608c.html

转载 2007年09月14日 17:44:00
我家有: 老婆, 儿子, 女儿.
我考虑写一个程序模拟她们的生活.
抽象出老婆,儿子和女儿这三个对象,为了易于统一管理和访问这些对象,同时抽象了一些公共基类:Baby.Baby要提供所有可能的接口. 为了把问题简单化,假设老婆主要照顾两个小宝贝和做家务(^-^); 两个小宝贝还小,基本上就是玩.于是我们建立下面的类模型:



根据这个模型,我们可以发现一些不足的地方:

1)抽象接口提供所有子类的行为接口
   抽象基类Baby为Wife,Son和Daughter提供了所有的接口,显得比较复杂。
2)子类必须要重写不属于自己的行为
   比如儿子比较小,是不参与家务的,但在程序中,Son必须重写Housework(),只是什么都不做。当然,通过某些方式可以避免这问题出现,但同时也会带来其它新问题。
3)增加新的行为比较烦琐
   在任何一个类中增加一个新行为,就要在所有的类中做修改。比如,小孩上小学了,老婆不须要照顾小孩了,要上班;同时儿子可能还要踢足球,女儿要课余要学唱歌、舞蹈等。系统不易扩展,增加新功能容易出错;而且会越来越复杂,不易维护。

有必要对设计进行优化,使系统更易扩展和维护。注意以上类结构的特点:Wife、Son、Daughter,这此元素比较稳定;但她们的行为容易变化。
因此我们很自然想到了采用Visitor,建立下面的类模型:

采用Visitor模式重新设计后,基本上消除了以上的不足之处。特别是要增加一个新行为,只要在Visitor层次增加一个新类,不会使系统越来越复杂。下面是针对采用Visitor后的代码实现。
说明:1)代码实现里的Visitor成员函数通过重载机制统一用Visit命名;
      2)为编排简单,所有成员函数定义在类声明里实现.

以下是Visitor层次的代码:

    struct Visitor
    {
        virtual void Visit(Wife& wife) = 0;
        virtual void Visit(Son& son) = 0;
       virtual void Visit(Daughter& daughter) = 0;
     };

    class BabysatVisitor : public Visitor
    {
     public:
        virtual void Visit(Wife& wife)
        {
              std::cout << "Wife is taking care of son and daughter./n";
        }

        virtual void Visit(Son& son){ }

        virtual void Visit(Daughter& daughter){ }
     };

HouseworkVisitor也是针对Wife的一个动作,实现和BabysatVisitor类似,略。

    class PalyVisitor : public Visitor
    {
     public:
        virtual void Visit(Wife& wife){ }

       virtual void Visit(Son& son)
        {
              std::cout << "Son is playing./n";
        }

        virtual void Visit(Daughter& daughter)
        {
             std::cout << "Daughter is playing./n";
        }
     };

以下元素层次的代码:

    struct Baby
    {
          virtual void Accept(Visitor& visitor) = 0;
    };

    class Wife : public Baby
    {
     public:
        virtual void Accept(Visitor& visitor)
        {
             visitor.Visit(*this);
         }
     };

Son和Daughter用同样的方法实现Accept,略.

最后用Family管理她们。

    class Family
    {
     public:

         typedef std::multimap<Baby*, Visitor*> BabyMap;

         Family()
         {
                babies_->insert(BabyMap::value_type(new Wife, new WifeVisitor));
                babies_->insert(BabyMap::value_type(new Son, new SonVisitor));
                babies_->insert(BabyMap::value_type(new Daughter, new DaughterVisitor));
         }

         void Behave()
         {
                for (BabyMap::const_iterator it = babies_.begin(); it != babies_.end(); ++it)
                     it->first->Accept(*it->second);
         }
     private:
          BabyMap babies_;
    };

主函数类似:

     Family family;

     family.Behave();

最后要说明的, 如果经常娶老婆或者经常有小宝宝出生的话,也就说像Wife这些节点容易变化的话, 使用Visitor模式不一定能带来多少好处.

 

相关文章推荐

关于sqlite3的性能(转自:http://hi.baidu.com/snailzone/blog/item/da9368662bc94f25aa184c2b.html)

我想对于80%的网站来说,它们的数据量采用access数据库已经足够了。使用mysql或者sqlserver这些中型数据库,往往需要增加额外的使用费,而且数据量不大的时候,它们所反映的性能跟acces...
  • lslxdx
  • lslxdx
  • 2011年11月06日 16:38
  • 1458

vim windows配置 http://hi.baidu.com/leemoncc/blog/item/a6be15cf40d7ab31b600c806.html

原作地址:http://hi.baidu.com/leemoncc/blog/item/a6be15cf40d7ab31b600c806.html 当然,对我的环境而言,有问题和有所修改。需要注...

javax.servlet.Filter详解(一)(转自:http://hi.baidu.com/jxnuywf/blog/item/33d96889c1dfa7b00f2444c2.html)

转自:http://hi.baidu.com/jxnuywf/blog/item/33d96889c1dfa7b00f2444c2.html或许,servlet API的2.3版本中最重要的一个新功能...
  • jubincn
  • jubincn
  • 2011年02月15日 11:51
  • 2003

java API提供的方法实现排序 如file按日期和大小排序(转:http://hi.baidu.com/axhack/blog/item/00514c0900605284d1581bab.html)

java API提供的方法实现排序 如file按日期和大小排序2008-10-06 23:25摘要:经常看见有人还在不厌其烦的用冒泡(最常见!)或是交换做排序,实际上用几行代码就可以既快又好地实现排序...
  • fjfdszj
  • fjfdszj
  • 2011年01月06日 22:49
  • 1073

C# 静态构造函数详解(转自:http://hi.baidu.com/jiang_yy_jiang/blog/item/07d5cbe9ff6b4d32b90e2d5a.html)

关于静态函数用的不多,但是在实际应用和代码中还是需要注意其细节的问题。静态成员在类中属于整个类的,而不是某一个单独的对象的。那么静态构造函数返回的就是整个类,而不是一个单独的实例成员,因此这只需要调用...
  • lslxdx
  • lslxdx
  • 2011年03月31日 16:48
  • 2419

sqlite使用手册(转自:http://hi.baidu.com/zifengshen/blog/item/671240f7e148f428720eec32.html)

建立数据库档案 用sqlite3建立数据库的方法很简单,只要在shell下键入(以下$符号为shell提示号,请勿键入): $ sqlite3 foo.db 如果目录下没有foo.d...
  • lslxdx
  • lslxdx
  • 2011年11月05日 21:13
  • 499

location.hash实现跨域iframe自适应(转自:http://hi.baidu.com/leolance/blog/item/2ec6f3ee5a7152c3d439c923.html)

使用iframe实现跨域自适应长宽
  • lslxdx
  • lslxdx
  • 2011年04月07日 13:31
  • 1329

MyEclipse安装SVN插件以及Myeclipse9.0(转载http://hi.baidu.com/zzcc_8/blog/item/5d6dd1f3be34e459342acc4f.html)

一、MyEclipse 6.X6.x的操作比较简单,可通过官方提供的链接,利用MyEclipse内置的Find and Install功能来安装。1. 打开Myeclipse,在菜单栏中选择Help→...

BMP图像结构(转自:http://hi.baidu.com/zybabiao/blog/item/1357d5fb21c06567034f56ee.html)

BMP图像资料 一、BMP文件结构   1. BMP文件组成   BMP文件由文件头、位图信息头、颜色信息和图形数据四部分组成。文件头主要包含文件的大小、文件类型、图...

FTP客户端软件FileZilla使用教程(转自:http://hi.baidu.com/%B8%DF%C7%E5%D6%AE%D3%D1/blog/item/36d6c8b6dc0589fc30a)

描述: FileZilla是一个免费开源的FTP客户端软件,分为客户端版本和服务器版本,具备所有的FTP软件功能.可控性、有条理的界面和管理多站点的简化方式使得Filezilla客户端版成为一个方便高...
  • lslxdx
  • lslxdx
  • 2011年09月29日 14:10
  • 1980
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:(转载)Visitor模式---实现家人行为 http://hi.baidu.com/huangrg/blog/item/aa9e46c7feaeebdfd100608c.html
举报原因:
原因补充:

(最多只允许输入30个字)