第二十三章烤羊肉串引来的思考--命令模式(读书笔记)

本文主要是介绍第二十三章烤羊肉串引来的思考--命令模式(读书笔记),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

第23章烤羊肉串引来的思考--命令模式

23.1 吃烤羊肉串

23.2 烧烤摊VS烧烤店
 要羊肉做生意的马路游击队,因为要吃烤肉的人太多,大家都希望能最快吃到肉串,而烤肉老板只有一个人,所以有些混乱。买羊肉串的人都盯着烤肉上去了。他们只关心哪一串多,哪一串少,哪一串考得好,这个其实就是行为请求着与行为实现者之间的紧耦合。
 对请求排队或记录请求日志,以及支持可撤销的操作等行为时,行为请求者与行为实现者的紧耦合是不太合适的。而在门店我们只需要给接待我们的服务员说我们要什么就可以了。收钱的时候也不会多收和少收。
 
23.3 紧耦合设计
 路边烤肉的对应。
 

23.4 松耦合设计

 
 抽象命令类, 具体命令类

#pragma once
#include "Barbecuer.h"
class Command
{
public:
Command(BarBecuer* receive)
{
m_pBarbecuer = receive;
};
virtual void ExcuteCommand(void) = 0;
protected:
BarBecuer* m_pBarbecuer;//野餐烤肉的人
};
//烤羊肉串
class BakeMuttonCommand : public Command
{
public:
BakeMuttonCommand(BarBecuer* receive)
:Command(receive)
{
};
void ExcuteCommand(void)
{
m_pBarbecuer->BakeMutton();
};
};
//烤鸡翅
class BakeChickenCommand : public Command
{
public:
BakeChickenCommand(BarBecuer* receive)
:Command(receive)
{
};
void ExcuteCommand(void)
{
m_pBarbecuer->BakeChickenWing();
};
};

服务员类

#pragma once
#include "command.h"
class Waiter
{
public:
//设置订单
void SetOrder(Command* pCommand)
{
m_pCommand = pCommand;
}; 
//通知执行
void Notify()
{
m_pCommand->ExcuteCommand();
};
private:
Command* m_pCommand;
};

羊肉串师傅

#pragma once
#include <iostream>
class BarBecuer
{
public:
void BakeMutton()
{
std::cout << "烤羊肉串" << std::endl;
};
void BakeChickenWing()
{
std::cout << "烤鸡翅" << std::endl;
};
};

 客户端

#include "Waiter.h"
int _tmain(int argc, _TCHAR* argv[])
{
BarBecuer* boy = new BarBecuer();
Command* bakeMuttonCommand1 = new BakeMuttonCommand(boy);
Command* bakeMuttonCommand2 = new BakeMuttonCommand(boy);
Command* bakeChickenWingCommand1 = new BakeChickenCommand(boy);
Waiter* girl = new Waiter();
girl->SetOrder(bakeMuttonCommand1);
girl->Notify();
girl->SetOrder(bakeMuttonCommand2);
girl->Notify();
girl->SetOrder(bakeChickenWingCommand1);
girl->Notify();
delete bakeMuttonCommand1;
delete bakeMuttonCommand2;
delete bakeChickenWingCommand1;
delete boy;
delete girl;
return 0;
}

 上面这个实现有下面这些问题点:1.用户并不是只点一个菜,2.如果没有鸡翅了,不应该由用户来判断,3.点的菜需要有日志,4.如果菜点了太多,没有取消的操作。

23.5 松耦合后
 这是小菜写的第三版的代码。

#pragma once
#include "command.h"
#include <iostream>
#include <list>
class Waiter
{
public:
//设置订单
void SetOrder(Command* pCommand)
{
m_list.push_back(pCommand);
}; 
//通知执行
void Notify()
{
//m_pCommand->ExcuteCommand();
if( !m_list.empty() )
{
m_iter = m_list.begin();
while(m_iter != m_list.end())
{
(*m_iter)->ExcuteCommand();
++m_iter;
}
}
};
//取消订单
void CancelOrder(Command* pCommand)
{
if( !m_list.empty() )
{
m_list.remove(pCommand);
}
};
private:
std::list<Command*> m_list;
std::list<Command*>::iterator m_iter;
//Command* m_pCommand;
};


 

#include "Waiter.h"
int _tmain(int argc, _TCHAR* argv[])
{
//开店前的准备
BarBecuer* boy = new BarBecuer();
Command* bakeMuttonCommand1 = new BakeMuttonCommand(boy);
Command* bakeMuttonCommand2 = new BakeMuttonCommand(boy);
Command* BakeChickenCommand1 = new BakeChickenCommand(boy);
Waiter* girl = new Waiter();
//开门营业顾客点菜
girl->SetOrder(bakeMuttonCommand1);
girl->SetOrder(bakeMuttonCommand2);
girl->SetOrder(BakeChickenCommand1);
girl->Notify();
delete boy;
delete bakeMuttonCommand1;
delete bakeMuttonCommand2;
delete BakeChickenCommand1;
delete girl;
return 0;
}

23.6 命令模式
  将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持撤销的操作。
 
 Command类,用来声明执行操作的接口。
 ConcreteCommand类,将一个接受者对象绑定于一个动作,调用接受者相应的操作,以实现Execute。

#pragma once
#include "Receiver.h"
class Command
{
public:
Command(Receiver* receiver)
{
m_receiver = receiver;
};
virtual void Execute(void) = 0;
protected:
Receiver* m_receiver;
};
class ConcreteCommand : public Command
{
public:
ConcreteCommand(Receiver* receiver)
:Command(receiver)
{
};
void Execute(void)
{
m_receiver->Action();
};
};

 Invoker类,要求该命令执行这个请求。

#pragma once
#include "Command.h"
class Invoker
{
public:
void SetCommand(Command* pCommand)
{
m_pCommand = pCommand;
};
void ExecuteCommand()
{
m_pCommand->Execute();
};
private:
Command* m_pCommand;
};

 Receiver类,直到如何实施与执行一个与请求相关的操作,任何类都可能作为一个接受者。

#pragma once
#include <iostream>
class Receiver
{
public:
void Action()
{
std::cout << "执行请求" << std::endl;
};
};

客户端

#include "stdafx.h"
#include "Invoker.h"
int _tmain(int argc, _TCHAR* argv[])
{
Receiver* rec = new Receiver();
Invoker* invoker = new Invoker();
Command* command = new ConcreteCommand(rec);
invoker->SetCommand(command);
invoker->ExecuteCommand();
delete rec;
delete invoker;
delete command;
return 0;
}

23.7 命令模式作用
 第一,它能较容易地设计一个命令队列;第二,在需要的情况下,可以较容易地将命令计入日志;第三,允许接收请求的一方决定是否要否决请求;第四,可以容易地实现对请求的撤销和重做;第五,由于加进新的具体命令类不影响其他的类,因此增加新的具体命令类很容易。其实还有最关键的优点就是命令模式把请求一个操作的对象与直到怎么执行一个操作的对象分割开。
 敏捷开发原则告诉我们,不要为代码添加基于猜测的,实际不需要的功能。如果不清楚一个系统是否需要命令模式,一般就不要着急去实现它,事实上,在需要的时候通过重构实现这个模式并不困难,只有在真正需要如撤销/恢复操作等功能时,把原来的代码重构为命令模式才有意义。
 再回到羊肉串的话题来,当服务员搞错价格的时候,服务员做了记录,也就是记日志,所以可以很快纠正过来。而单就烤肉串的人,哪里记得住烤了多少串,如果人一多,则必定会搞错。

这篇关于第二十三章烤羊肉串引来的思考--命令模式(读书笔记)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/832338

相关文章

setsid 命令工作原理和使用案例介绍

《setsid命令工作原理和使用案例介绍》setsid命令在Linux中创建独立会话,使进程脱离终端运行,适用于守护进程和后台任务,通过重定向输出和确保权限,可有效管理长时间运行的进程,本文给大家介... 目录setsid 命令介绍和使用案例基本介绍基本语法主要特点命令参数使用案例1. 在后台运行命令2.

Linux如何查看文件权限的命令

《Linux如何查看文件权限的命令》Linux中使用ls-R命令递归查看指定目录及子目录下所有文件和文件夹的权限信息,以列表形式展示权限位、所有者、组等详细内容... 目录linux China编程查看文件权限命令输出结果示例这里是查看tomcat文件夹总结Linux 查看文件权限命令ls -l 文件或文件夹

idea的终端(Terminal)cmd的命令换成linux的命令详解

《idea的终端(Terminal)cmd的命令换成linux的命令详解》本文介绍IDEA配置Git的步骤:安装Git、修改终端设置并重启IDEA,强调顺序,作为个人经验分享,希望提供参考并支持脚本之... 目录一编程、设置前二、前置条件三、android设置四、设置后总结一、php设置前二、前置条件

Linux系统之lvcreate命令使用解读

《Linux系统之lvcreate命令使用解读》lvcreate是LVM中创建逻辑卷的核心命令,支持线性、条带化、RAID、镜像、快照、瘦池和缓存池等多种类型,实现灵活存储资源管理,需注意空间分配、R... 目录lvcreate命令详解一、命令概述二、语法格式三、核心功能四、选项详解五、使用示例1. 创建逻

C语言进阶(预处理命令详解)

《C语言进阶(预处理命令详解)》文章讲解了宏定义规范、头文件包含方式及条件编译应用,强调带参宏需加括号避免计算错误,头文件应声明函数原型以便主函数调用,条件编译通过宏定义控制代码编译,适用于测试与模块... 目录1.宏定义1.1不带参宏1.2带参宏2.头文件的包含2.1头文件中的内容2.2工程结构3.条件编

nginx -t、nginx -s stop 和 nginx -s reload 命令的详细解析(结合应用场景)

《nginx-t、nginx-sstop和nginx-sreload命令的详细解析(结合应用场景)》本文解析Nginx的-t、-sstop、-sreload命令,分别用于配置语法检... 以下是关于 nginx -t、nginx -s stop 和 nginx -s reload 命令的详细解析,结合实际应

C#连接SQL server数据库命令的基本步骤

《C#连接SQLserver数据库命令的基本步骤》文章讲解了连接SQLServer数据库的步骤,包括引入命名空间、构建连接字符串、使用SqlConnection和SqlCommand执行SQL操作,... 目录建议配合使用:如何下载和安装SQL server数据库-CSDN博客1. 引入必要的命名空间2.

Linux系统性能检测命令详解

《Linux系统性能检测命令详解》本文介绍了Linux系统常用的监控命令(如top、vmstat、iostat、htop等)及其参数功能,涵盖进程状态、内存使用、磁盘I/O、系统负载等多维度资源监控,... 目录toppsuptimevmstatIOStatiotopslabtophtopdstatnmon

PowerShell中15个提升运维效率关键命令实战指南

《PowerShell中15个提升运维效率关键命令实战指南》作为网络安全专业人员的必备技能,PowerShell在系统管理、日志分析、威胁检测和自动化响应方面展现出强大能力,下面我们就来看看15个提升... 目录一、PowerShell在网络安全中的战略价值二、网络安全关键场景命令实战1. 系统安全基线核查

Java设计模式---迭代器模式(Iterator)解读

《Java设计模式---迭代器模式(Iterator)解读》:本文主要介绍Java设计模式---迭代器模式(Iterator),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录1、迭代器(Iterator)1.1、结构1.2、常用方法1.3、本质1、解耦集合与遍历逻辑2、统一