蛋疼的命令模式。(转)

还是简单的记录一下自己的理解。命令模式下,invoker于最后提供实现的对象receiver没有直接接触。

invoker执行一个命令(方法),方法就是执行command对象里面的方法,该command对象里面包含了receiver对象。

invoker就执行了一个命令,后面的具体逻辑可以交给command里面去执行,所有每一个commmand如果需要不同的操作,需要继承不同的Com对象。

Fluent Python一书中可以将函数当做对象传入com对象里面传入函数,让里面的函数去执行各个不同的操作。

原帖地址:https://blog.csdn.net/Yuyh131/article/details/83215139

命令模式-封装调用

这章讨论行为型设计模式:命令模式
本章主题

命令设计模式简介
    命令模式及其 UML图
    Python3.x 代码实现的真实用例
    命令模式的优缺点
    常见问答

1. 命令设计模式简介

行为模式侧重于对象的响应性,它利用对象之间的交互实现更强大的功能
命令模式是一种行为设计模式,其中对象用于封装完成一项操作时或在触发一个事件时所需的全部信息。这些信息包括:

方法名称;
    拥有方法的对象;
    方法参数的值

2. 了解命令设计模式

命令模式通常使用以下术语:Command, Receiver, Invoker, Client

命令模式的主要意图:

将请求封装为对象
    可用不同的请求对客户进行参数化
    允许将请求保存在队列中
    提供面向对象的回调

命令模式应用场景:

根据需要执行的操作对对象进行参数化
    将操作添加到队列并在不同地点执行请求
    创建一个结构来根据较小操作完成高级操作

以下 Python代码实现了命令模式:

class Wizard():

def __init__(self, src, rootdir):
        self.choices = []
        self.rootdir = rootdir
        self.src = src

def preferences(self, command):
        self.choices.append(command)

def execute(self):
        for choice in self.choices:
            if list(choice.values())[0]:
                print("Copying binaries --", self.src,
                      " to ", self.rootdir)
            else:
                print("No Operation")

if __name__ == "__main__":
    wizard = Wizard(‘python3.6.gzip‘, ‘/usr/bin/‘)

wizard.preferences({‘python‘: True})
    wizard.preferences({‘java‘: False})

wizard.execute()

运行结果:
Copying binaries – python3.6.gzip to /usr/bin/
No Operation
3. 命令模式的 UML类图

CommandPattern-UML-image

可以发现,命令模式主要涉及5个参与者:

Command: 声明执行操作的接口
    ConcreteCommand: 将一个 Receiver对象和一个操作进行绑定
    Client: 创建 ConcreteCommand对象并设定其接收对象
    Invoker: 要求该 ConcreteCommand执行这个请求
    Receiver: 要知道如何实施与执行一个请求相关的操作

这个流程是这样的:
客户端请求执行命名,调用者接受命令,封装它并将其放置到队列中
ConcreteCommand类根据所请求的命命令来指导接收者执行特定的动作

下面通过代码理解命令模式的所有参与者的情况:

from abc import ABCMeta, abstractmethod

class Command(metaclass=ABCMeta):

def __init__(self, receiver):
        self.receiver = receiver

@abstractmethod
    def execute(self):
        pass

class ConcreteCommand(Command):
    def __init__(self, receiver):
        super().__init__(receiver)
        self.receiver = receiver

def execute(self):
        self.receiver.action()

class Receiver:
    def action(self):
        print("Receiver Action")

class Invoker:
    def command(self, cmd):
        self.cmd = cmd

def execute(self):
        self.cmd.execute()

if __name__ == "__main__":
    receiver = Receiver()
    cmd = ConcreteCommand(receiver)

invoker = Invoker()
    invoker.command(cmd)
    invoker.execute()

运行结果:
Receiver Action
4. 实现现实世界中的命令模式

from abc import ABCMeta, abstractmethod

# 订单基类(Command)
class Order:
    @abstractmethod
    def execute(self):
        pass

# 购买股票的订单(ConcreteCommand)
class BuyStockOrder(Order):
    def __init__(self, stock):
        self.stock = stock

# 执行买的操作
    def execute(self):
        self.stock.buy()

# 卖股票的接口(ConcreteCommand)
class SellStockOrder(Order):
    def __init__(self, stock):
        self.stock = stock

def execute(self):
        self.stock.sell()

# 股票交易
class StockTrade:
    def buy(self):
        print("You will buy stocks")

def sell(self):
        print("You will sell stocks")

# 代理(invoker)
class Agent:
    def __init__(self):
        self.__orderQueue = []

def placeOrder(self, order):
        self.__orderQueue.append(order)
        order.execute()

if __name__ == "__main__":
    # client
    stock = StockTrade()
    buyStock = BuyStockOrder(stock)
    sellStock = SellStockOrder(stock)

# invoker
    agent = Agent()
    agent.placeOrder(buyStock)
    agent.placeOrder(sellStock)

运行结果:
You will buy stocks
You will sell stocks

在软件中应用命令模式的方式有很多种,这里讨论与云应用密切相关的两个实现:

重做或回滚操作:
    – 在实现回滚或重做操作时,开发人员可以做两件不同的事情
    – 这些是在文件系统或内存中创建快照,当被要求回滚时,恢复到该快照
    – 使用命令模式时,可以存储命令序列,并且要求进行重做时,重新运行相同的一组操作即可

异步任务执行:
    – 在分布式系统中,我们通常要求设备具备异步执行任务的功能,以便核心服务在大量请求涌来时不会发生阻塞
    – 在命令模式中,Invoker 对象可以维护一个请求队列,并将这些任务发送到 Receiver对象,以便它们可以独立于主应用程序线程来完成相应的操作

5. 命令模式的优缺点

命令模式优点:

将调用操作的类与知道如何执行该操作的对象解耦
    提供队列系统后,可以创建一系列命令
    添加新命令更加容易,并且无需更改现有代码
    还可以使用命令模式来定义回滚系统,如:在向导实例中,我们可以编写一个回滚方法

命令模式的缺点:

为了实现目标,需要大量的类和对象进行协作。应用程序开发人员为了正确开发这些类,需要倍加小心
    每个单独的命令都是一个 ConcreteCommand类,从而增加了需要实现和维护的类的数量

6. 常见问答

命令模式中是否可以不实现Receiver和ConcreteCommand?
    是的,可以。许多软件应用程序也就是通过这种方式来使用命令模式的。这里唯一要注意的是调用者和接收者之间的交互了。如果接收器未被定义的话,则去耦程度机会下降;此外,参数化的优势也就不复存在了

我使用什么数据结构来实现Invoker对象中的队列机制?
    在本章中的股票交易示例,我们使用一个列表来实现队列。但是,命令模式还可以使用一个堆栈来实现队列机制,这在开发具有重做或回滚功能的时候常有帮助

7. 小结

命令模式的概念和在软件架构中有效使用
    如何使用命令模式来封装在稍后某个时间点触发事件或动作所需的所有信息
    使用UML类图和Python3.x代码示例来进一步理解命令模式
    问答部分提供与命令模式相关的设计思想,还介绍了该模式的优缺点

版权声明:本文为CSDN博主「E.Wong」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Yuyh131/article/details/83215139

原文地址:https://www.cnblogs.com/sidianok/p/12065043.html

时间: 2024-09-29 05:06:29

蛋疼的命令模式。(转)的相关文章

设计模式 命令模式 之 管理智能家电

继续设计模式哈,今天带来命令模式,二话不说,先看定义: 定义:将“请求”封装成对象,以便使用不同的请求.队列或者日志来参数化其他对象.命令模式也支持可撤销的操作. 这尼玛定义,看得人蛋疼,看不明白要淡定,我稍微简化一下:将请求封装成对象,将动作请求者和动作执行者解耦.好了,直接用例子来说明. 需求:最近智能家电很火热啊,未来尼玛估计冰箱都会用支付宝自动买东西了,,,,假设现在有电视.电脑.电灯等家电,现在需要你做个遥控器控制所有家电的开关,要求做到每个按钮对应的功能供用户个性化,对于新买入家电要

5.5 进入编辑模式 5.6 vim命令模式 5.7 vim实践

5.5 进入编辑模式 5.6 vim命令模式 5.7 vim实践 扩展 vim的特殊用法 http://www.apelearn.com/bbs/thread-9334-1-1.html vim常用快捷键总结 http://www.apelearn.com/bbs/thread-407-1-1.html vim快速删除一段字符 http://www.apelearn.com/bbs/thread-842-1-1.html vim乱码 http://www.apelearn.com/bbs/thr

Ubuntu命令模式基础

Ubuntu是一个自由.开源.基于Debian的Linux发行版.在ubuntu的基础上,又衍生其它各具特色的Linux发行版.首先是一个操作系统,操作系统用于管理电脑硬件.要发挥出电脑的作用,还得依靠安装各种应用软件. 其相关的简单命令如下: (1)查看当前文件夹下的目录 ①.ls (list的缩写)命令用于列出文件和目录.默认上,他会列出当前目录的内容.带上参数后,可以以不同的方式显示.如图: ls命令可以列出当前目录的内容.dir命令是ls命令的一个别名,也是directory的缩写.通常

【游戏设计模式】之二 实现撤消重做、回放系统的神器:命令模式

本系列文章由@浅墨_毛星云 出品,转载请注明出处.   文章链接:http://blog.csdn.net/poem_qianmo/article/details/52663057 作者:毛星云(浅墨)    微博:http://weibo.com/u/1723155442 这篇文章将与大家一起探索游戏开发中命令模式的用法. 命令模式的成名应用是实现诸如撤消,重做,回放,时间倒流之类的功能.如果你想知道<Dota2>中的观战系统.<魔兽争霸3>中的录像系统.<守望先锋>

命令模式

1.命令模式:将一个请求封装为一个对象,从而使你可以用不同的请求对客户进行参数化:对请求排列或记录请求日志,以及支持可以撤销的操作. 2.优点:(1).他能比较容易的设计一个命令队列:(2).在需要的情况下,比较容易的将命令记入日志:(3).允许接收请求的一方决定是否否决请求:(4).可以容易地实现对请求的撤销和重做:(5).由于加进新的具体命令类不影响其它类,因此增加新的具体命令很容易.(6).把请求一个操作的对象与指导怎么执行操作对象分隔开. 3.注意:不要为代码添加基于猜测的.实际不需要的

【设计模式】 模式PK:命令模式VS策略模式

1.概述 命令模式和策略模式的类图确实很相似,只是命令模式多了一个接收者(Receiver)角色.它们虽然同为行为类模式,但是两者的区别还是很明显的.策略模式的意图是封装算法,它认为"算法"已经是一个完整的.不可拆分的原子业务(注意这里是原子业务,而不是原子对象),即其意图是让这些算法独立,并且可以相互替换,让行为的变化独立于拥有行为的客户:而命令模式则是对动作的解耦,把一个动作的执行分为执行对象(接收者角色).执行行为(命令角色),让两者相互独立而不相互影响. 我们从一个相同的业务需

设计模式—命令模式

1 概述 将一个请求封装为一个对象(即我们创建的Command对象),从而使你可用不同的请求对客户进行参数化:对请求排队或记录请求日志,以及支持可撤销的操作. 2 解决的问题 在软件系统中,行为请求者与行为实现者通常是一种紧耦合的关系,但某些场合,比如需要对行为进行记录.撤销或重做.事务等处理时,这种无法抵御变化的紧耦合的设计就不太合适. 3 模式中的角色 3.1 抽象命令(Command):定义命令的接口,声明执行的方法. 3.2 具体命令(ConcreteCommand):具体命令,实现要执

javascript设计模式详解之命令模式

每种设计模式的出现都是为了弥补语言在某方面的不足,解决特定环境下的问题.思想是相通的.只不过不同的设计语言有其特定的实现.对javascript这种动态语言来说,弱类型的特性,与生俱来的多态性,导致某些设计模式不自觉的我们都在使用.只不过没有对应起来罢了.本文就力求以精简的语言去介绍下设计模式这个高大上的概念.相信会在看完某个设计模式之后有原来如此的感慨. 一.基本概念与使用场景: 基本概念: 将请求封装成对象,分离命令接受者和发起者之间的耦合. 命令执行之前在执行对象中传入接受者.主要目的相互

设计模式完结(14)-- 命令模式 --- 请求发送者与接收者解耦

起连接作用:  类似开关   和  电器  之间的   电线 请求发送者与接收者解耦,  引入命令类 abstract class Command { public abstract void execute(); } class Invoker { private Command command; //构造注入 public Invoker(Command command) { this.command = command; } //设值注入 public void setCommand(Co