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

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

第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

相关文章

Linux使用dd命令来复制和转换数据的操作方法

《Linux使用dd命令来复制和转换数据的操作方法》Linux中的dd命令是一个功能强大的数据复制和转换实用程序,它以较低级别运行,通常用于创建可启动的USB驱动器、克隆磁盘和生成随机数据等任务,本文... 目录简介功能和能力语法常用选项示例用法基础用法创建可启动www.chinasem.cn的 USB 驱动

关于Maven生命周期相关命令演示

《关于Maven生命周期相关命令演示》Maven的生命周期分为Clean、Default和Site三个主要阶段,每个阶段包含多个关键步骤,如清理、编译、测试、打包等,通过执行相应的Maven命令,可以... 目录1. Maven 生命周期概述1.1 Clean Lifecycle1.2 Default Li

windows系统下shutdown重启关机命令超详细教程

《windows系统下shutdown重启关机命令超详细教程》shutdown命令是一个强大的工具,允许你通过命令行快速完成关机、重启或注销操作,本文将为你详细解析shutdown命令的使用方法,并提... 目录一、shutdown 命令简介二、shutdown 命令的基本用法三、远程关机与重启四、实际应用

Linux使用nohup命令在后台运行脚本

《Linux使用nohup命令在后台运行脚本》在Linux或类Unix系统中,后台运行脚本是一项非常实用的技能,尤其适用于需要长时间运行的任务或服务,本文我们来看看如何使用nohup命令在后台... 目录nohup 命令简介基本用法输出重定向& 符号的作用后台进程的特点注意事项实际应用场景长时间运行的任务服

Redis的Hash类型及相关命令小结

《Redis的Hash类型及相关命令小结》edisHash是一种数据结构,用于存储字段和值的映射关系,本文就来介绍一下Redis的Hash类型及相关命令小结,具有一定的参考价值,感兴趣的可以了解一下... 目录HSETHGETHEXISTSHDELHKEYSHVALSHGETALLHMGETHLENHSET

如何使用 Bash 脚本中的time命令来统计命令执行时间(中英双语)

《如何使用Bash脚本中的time命令来统计命令执行时间(中英双语)》本文介绍了如何在Bash脚本中使用`time`命令来测量命令执行时间,包括`real`、`user`和`sys`三个时间指标,... 使用 Bash 脚本中的 time 命令来统计命令执行时间在日常的开发和运维过程中,性能监控和优化是不

PHP执行php.exe -v命令报错的解决方案

《PHP执行php.exe-v命令报错的解决方案》:本文主要介绍PHP执行php.exe-v命令报错的解决方案,文中通过图文讲解的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下... 目录执行phpandroid.exe -v命令报错解决方案执行php.exe -v命令报错-PHP War

CentOS系统使用yum命令报错问题及解决

《CentOS系统使用yum命令报错问题及解决》文章主要讲述了在CentOS系统中使用yum命令时遇到的错误,并提供了个人解决方法,希望对大家有所帮助,并鼓励大家支持脚本之家... 目录Centos系统使用yum命令报错找到文件替换源文件为总结CentOS系统使用yum命令报错http://www.cppc

在JS中的设计模式的单例模式、策略模式、代理模式、原型模式浅讲

1. 单例模式(Singleton Pattern) 确保一个类只有一个实例,并提供一个全局访问点。 示例代码: class Singleton {constructor() {if (Singleton.instance) {return Singleton.instance;}Singleton.instance = this;this.data = [];}addData(value)

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]