两种语言实现设计模式(C++和Java)(十九:访问者模式)

在现实生活中,有些集合对象中存在多种不同的元素,且每种元素也存在多种不同的访问者和处理方式。例如,公园中存在多个景点,也存在多个游客,不同的游客对同一个景点的评价可能不同;医院医生开的处方单中包含多种药元素,査看它的划价员和药房工作人员对它的处理方式也不同,划价员根据处方单上面的药品名和数量进行划价,药房工作人员根据处方单的内容进行抓药。

UML:

Visitor Pattern 优缺点:

访问者(Visitor)模式是一种对象行为型模式,其主要优点如下。

  1. 扩展性好。能够在不修改对象结构中的元素的情况下,为对象结构中的元素添加新的功能。
  2. 复用性好。可以通过访问者来定义整个对象结构通用的功能,从而提高系统的复用程度。
  3. 灵活性好。访问者模式将数据结构与作用于结构上的操作解耦,使得操作集合可相对自由地演化而不影响系统的数据结构。
  4. 符合单一职责原则。访问者模式把相关的行为封装在一起,构成一个访问者,使每一个访问者的功能都比较单一。

访问者(Visitor)模式的主要缺点如下。

  1. 增加新的元素类很困难。在访问者模式中,每增加一个新的元素类,都要在每一个具体访问者类中增加相应的具体操作,这违背了“开闭原则”。
  2. 破坏封装。访问者模式中具体元素对访问者公布细节,这破坏了对象的封装性。
  3. 违反了依赖倒置原则。访问者模式依赖了具体类,而没有依赖抽象类。

举例:在药房拿药

C++ Code:

  1 #include <iostream>
  2 #include <string>
  3 #include <list>
  4 using namespace std;
  5 
  6 class Element;
  7 
  8 class Visitor
  9 {
 10 public:
 11     virtual void Visit( Element *element ){};
 12 };
 13 
 14 // "Element"
 15 class Element
 16 {
 17 public:
 18     // Methods
 19     virtual void Accept( Visitor *visitor ){};
 20 };
 21 
 22 
 23 // "ConcreteElement"
 24 class Employee : public Element
 25 {
 26 public:
 27     string name;
 28     double income;
 29     int vacationDays;
 30 
 31 public :
 32     Employee( string name, double income,
 33         int vacationDays )
 34     {
 35         this->name = name;
 36         this->income = income;
 37         this->vacationDays = vacationDays;
 38     }
 39 
 40     void Accept( Visitor *visitor )
 41     {
 42         visitor->Visit( this );
 43     }
 44 };
 45 
 46 class IncomeVisitor : public Visitor
 47 {
 48 public:    
 49     void Visit( Element *element )
 50     {
 51         Employee *employee = ((Employee*)element);
 52         employee->income *= 1.10;
 53         cout<<employee->name<<" 's new income: " <<employee->income<<endl;
 54 
 55     }
 56 };
 57 
 58 class VacationVisitor : public Visitor
 59 {
 60 public :
 61     void Visit( Element *element )
 62     {
 63         Employee *employee = ((Employee*)element);
 64         // Provide 3 extra vacation days
 65         employee->vacationDays += 3;        
 66         cout<<employee->name<<" 's new vacation days: " <<employee->income<<endl;
 67     }
 68 };
 69 
 70 // "ObjectStructure"
 71 class Employees
 72 {    
 73 private :
 74     list< Employee*> employees;
 75 
 76 public :
 77 
 78     void Attach( Employee *employee )
 79     {        
 80         employees.push_back(employee);        
 81     }
 82 
 83     void Detach( Employee *employee )
 84     {
 85         employees.remove(employee);        
 86     }
 87 
 88     void Accept( Visitor *visitor )
 89     {        
 90         for (std::list<Employee*>::iterator it=employees.begin(); it != employees.end(); ++it)
 91             (*it)->Accept(visitor);
 92     }
 93 };
 94 
 95 void main( )
 96 {
 97     Employees *e = new Employees();
 98     e->Attach( new Employee( "Tom", 25000.0, 14 ) );
 99     e->Attach( new Employee( "Thomas", 35000.0, 16 ) );
100     e->Attach( new Employee( "Roy", 45000.0, 21 ) );
101 
102     // Create two visitors
103     IncomeVisitor *v1 = new IncomeVisitor();
104     VacationVisitor *v2 = new VacationVisitor();
105 
106     // Employees are visited
107     e->Accept( v1 );
108     e->Accept( v2 );
109 }

猜你喜欢

转载自www.cnblogs.com/Asp1rant/p/11391593.html
今日推荐