【设计模式学习笔记】访问者模式、状态模式案例详解(C++实现)

简介: 【设计模式学习笔记】访问者模式、状态模式案例详解(C++实现)

一、访问者模式

1. 什么是访问者模式

Visitor Pattern,访问者模式,是一种行为型设计模式。访问者模式把数据结构和作用于数据结构上的操作进行了分离,在不修改已有类的前提下可以增加新的操作,而新增新的操作就相当于新增一个访问者。

  • Visitor:抽象访问者角色,声明了访问操作的方法,方法的参数为被访问的元素;
  • ConcreteVisitor:具体访问者角色,实现抽象访问者中声明的方法;
  • Element:抽象元素角色,声明接受访问的操作,并接收一个访问者对象作为参数;
  • ConcreteElement:具体元素角色,实现被访问的操作;
  • ObjectStructure:结构对象角色,包含一个具体元素的引用的容器;

2. 访问者模式案例

定义一个抽象访问者类和一个抽象元素类

1. class Element;
2. 
3. class Visitor //抽象访问者
4. {
5. public:
6.  virtual void visit(Element* e) = 0;
7. };
8. 
9. class Element //抽象元素
10. {
11. public:
12.   virtual void reception(Visitor* v) = 0;
13.   virtual string get_name() = 0;
14. };

以领导访问公司部门为例,创建两个公司部门

1. class Department1 : public Element //部门1
2. {
3. public:
4.  virtual void reception(Visitor* v)
5.  {
6.    v->visit(this);
7.  }
8.  virtual string get_name()
9.  {
10.     return "第一事业部";
11.   }
12. };
13. 
14. class Department2 : public Element //部门2
15. {
16. public:
17.   virtual void reception(Visitor* v)
18.   {
19.     v->visit(this);
20.   }
21.   string get_name()
22.   {
23.     return "第二事业部";
24.   }
25. };

创建访问者,董事长和部门分管领导

1. class President : public Visitor //董事长
2. {
3. public:
4.  virtual void visit(Element* e)
5.  {
6.    cout << "董事长访问:" << e->get_name() << endl;
7.  }
8. };
9. 
10. class Leader1 : public Visitor //分管领导1
11. {
12. public:
13.   virtual void visit(Element* e)
14.   {
15.     cout << "第一分管领导访问:" << e->get_name() << endl;
16.   }
17. };
18. 
19. class Leader2 : public Visitor //分管领导2
20. {
21. public:
22.   virtual void visit(Element* e)
23.   {
24.     cout << "第二分管领导访问:" << e->get_name() << endl;
25.   }
26. };

首先在客户端实现,分管部门的领导对自己的部门进行访问

1. {    
2.     v1 = new Leader1;
3.  v2 = new Leader2;
4. 
5.  e1 = new Department1;
6.  e2 = new Department2;
7. 
8.  e1->reception(v1);
9.  e2->reception(v2);
10. }

然后我们在客户端增加操作,假设董事长要来视察,因为董事长职位最大,可以对整个公司进行访问,这是可以创建一个结构对象角色,把所有的部门都包含进来

1. class Group : public Element //整个集团
2. {
3. private:
4.  list<Element*> l;
5. public:
6.  virtual void reception(Visitor* v)
7.  {
8.    for (list<Element*>::iterator it = l.begin(); it != l.end(); it++)
9.    {
10.       (*it)->reception(v);
11.     }
12.   }
13.   void add_element(Element* e)
14.   {
15.     l.push_back(e);
16.   }
17.   virtual string get_name()
18.   {
19.     return "整个集团公司";
20.   }
21. };

然后在客户端进行操作,首先把各个部门对象加入到集团公司对象中,然后董事长进行访问

1. {
2.     v = new President;
3. 
4.  e = new Group;
5.  e1 = new Department1;
6.  e2 = new Department2;
7. 
8.  //组织集团架构  加入所有部门
9.  e->add_element(e1);
10.   e->add_element(e2);
11. 
12. //董事长访问
13.   e->reception(v);
14. }

二、状态模式

1. 什么是状态模式

State Pattern,状态模式,是一种行为型设计模式。通过改变对象的内部状态来达到改变对象行为的目的,“这个对象表现得就好像改变了它的类一样”。其实说白了就是,根据用户是输入的条件,满足一定条件就改变对象的行为,不同条件执行不同的操作。

  • State:抽象状态,定义了一个接口,接口声明了一个与上下文环境相关的状态的行为;
  • ConcreteState:具体状态,定义了本状态的行为和转换到另一个状态的判定条件;
  • Context:上下文、环境,负责状态的转换,包含了一个表示当前状态的State类型的引用;

2. 状态模式案例

定义状态类

1. class State
2. {
3. public:
4.  virtual void get_state(Machine* m) = 0;
5. };
6. 
7. class State1 : public State
8. {
9. public:
10.   virtual void get_state(Machine* m);
11. };
12. 
13. class State2 : public State //状态2
14. {
15. public:
16.   virtual void get_state(Machine* m);
17. };

实现状态对应行为

1. void State1::get_state(Machine* m)
2. {
3.  if (m->get_flag() == 1)
4.  {
5.    //当前状态标志是1,则执行状态1
6.    cout << "执行状态1" << endl;
7.  }
8.  else
9.  {
10.     //当前状态标志不是1,则切换为状态2
11. 
12.     //删除原来的状态
13.     delete m->get_current();
14.     //把当前状态设置为状态2
15.     m->set_flag(2);
16.     m->set_current(new State2);
17.     //执行状态
18.     m->get_current()->get_state(m);
19.   }
20. }
21. 
22. void State2::get_state(Machine* m)
23. {
24.   if (m->get_flag() == 2)
25.   {
26.     cout << "执行状态2" << endl;
27.   }
28.   else
29.   {
30.     //删除原状态
31.     delete m->get_current();
32.     //设置新的当前状态
33.     m->set_flag(1);
34.     m->set_current(new State1);
35.     //执行当前状态
36.     m->get_current()->get_state(m);
37.   }
38. }

定义一个Context类

1. class Machine
2. {
3. private:
4.  State* current; //当前状态
5.  int flag; //状态标志
6. public:
7.  State* get_current()
8.  {
9.    return this->current;
10.   }
11.   void set_current(State* s)
12.   {
13.     this->current = s;
14.   }
15.   void set_flag(int flag)
16.   {
17.     this->flag = flag;
18.   }
19.   void execute_state()
20.   {
21.     current->get_state(this);
22.   }
23.   int get_flag()
24.   {
25.     return flag;
26.   }
27. };

客户端实现状态行为的执行和转换

1. int main()
2. {
3.  Machine* m = NULL;
4.  State* s = NULL;
5. 
6.  m = new Machine;
7. 
8.  cout << "======初始状态======" << endl;
9.  //初始化为状态1
10.   s = new State1;
11.   m->set_flag(1);
12.   m->set_current(s);
13.   m->execute_state();
14. 
15.   cout << "======切换为状态2======" << endl;
16.   //切换为状态2
17.   m->set_flag(2);
18.   m->execute_state();
19. 
20.   cout << "======切换为状态1======" << endl;
21.   //切换为状态1
22.   m->set_flag(1);
23.   m->execute_state();
24. 
25.   delete s;
26.   delete m;
27. 
28.   system("pause");
29.   return 0;
30. }


相关文章
|
4月前
|
C++
c++学习笔记07 结构体
C++结构体的详细学习笔记07,涵盖了结构体的定义、使用、数组、指针、嵌套、与函数的交互以及在结构体中使用const的示例和解释。
40 0
|
3月前
|
编译器 C++
【C++核心】指针和引用案例详解
这篇文章详细讲解了C++中指针和引用的概念、使用场景和操作技巧,包括指针的定义、指针与数组、指针与函数的关系,以及引用的基本使用、注意事项和作为函数参数和返回值的用法。
52 3
|
3月前
|
C++
【C++案例】一个项目掌握C++基础-通讯录管理系统
这篇文章通过一个通讯录管理系统的C++项目案例,详细介绍了如何使用C++实现添加、显示、删除、查找、修改和清空联系人等功能。
52 3
|
3月前
|
安全 C语言 C++
C++学习笔记
C++学习笔记
|
4月前
|
C++
【学习笔记】【C/C++】 c++字面值常量
【学习笔记】【C/C++】 c++字面值常量
44 1
|
3月前
|
JavaScript 前端开发 测试技术
一个google Test文件C++语言案例
这篇文章我们来介绍一下真正的C++语言如何用GTest来实现单元测试。
25 0
|
4月前
|
编译器 C++
【C/C++学习笔记】C++声明与定义以及头文件与源文件的用途
【C/C++学习笔记】C++声明与定义以及头文件与源文件的用途
56 0
|
4月前
|
存储 C++
【C/C++学习笔记】string 类型的输入操作符和 getline 函数分别如何处理空白字符
【C/C++学习笔记】string 类型的输入操作符和 getline 函数分别如何处理空白字符
45 0
|
19天前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
29 2
|
25天前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
61 5