Head First设计模式(阅读笔记)-06.命令模式

news2025/1/15 23:49:32

家电自动化遥控器

假设要创建一个遥控器,该遥控器上有7个插槽(每个可以插上不同的家电),每个插槽对应了开关按钮,并且遥控器上还有一个撤销按钮用于撤销上一次的操作


从餐厅点餐开始

假设一个顾客来到餐厅要进行点餐,整体流程如下:

  • 顾客点了需要的食物(createOrder),生成了一个订单
  • 服务员拿走订单(takeOrder),放在订单柜台并通知厨师准备(orderUp)
  • 厨师根据订单上的指示进行操作(makeBurger)
  • 做好后顾客就可以开吃了

  • 服务员不必关心订单的内容,只需要接过不同订单(相当于takeOrder中传入不同参数)然后调用订单上的orderUp方法
  • 厨师和服务员不需要沟通(相当于解耦),它只需要看订单上的请求就知道该做什么餐了

命令模式

  • 命令模式将请求封装为对象,以便使用不同的请求、队列或日志来参数化其他对象
  • 命令对象将动作和接收者包进对象中,该对象只暴露出excute方法,该方法被调用时接收者就进行这些动作,外部不知道进行了哪些动作,只需要知道调用excute方法,请求的目的就能达成(比如插槽不需要知道插入的时什么电器,执行excute方法就行)
  • 命令模式将发出请求的对象和执行请求的对象进行解耦,这两种通过命令对象进行交流
  • 命令可以实现日志和事务系统

在这里插入图片描述


分析点餐


餐厅命令模式
服务员Invoker
厨师Receiver
orderUp()execute()
订单Command
顾客Client
takeOrder()setCommand()

在这里插入图片描述

开始设计遥控器

该部分介绍大致设计步骤


  • 实现命令接口
// 可以理解为点餐的订单
public interface Command{
    public void execute();
    public void undo();
}
  • 实现打开电灯的命令
public class LightOnCommand implements Command{
    Light light;  // 有on和off方法(相当于厨师)
    public LightOnCommand(Light light){
        this.light = light;
    }
    // 该订单上写明要的餐(即要求厨师需要执行什么操作)
    public void execute(){
        light.on();  // 电灯变为接收者,负责接收请求
    }
    // 撤销就是做一个相反的操作
    public void undo(){
        light.off();
    }
}
  • 使用命令对象:
// 相当于服务员
public class SimpleRemoteControl{
	Command slot; 
    public SimpleRemoteControl(){}
    // 服务员拿走顾客下好的单
    public void setCommand(Command command){ 
        slot = command;
    }
    // 按下按钮则调用该方法(服务员把订单放在厨师台,让厨师开始执行订单)
    public void buttonWasPressed(){  
        slot.execute();
    }
}
  • 测试遥控器:
// 相当于Client
public class RemoteControlTest{
	public static void main(String[] args){
        // 遥控器为调用者,传入一个命令对象然后发出请求
        SimpleRemoteControl remote = new SimpleRemoteControl();
    	Light light = new Light();  // 请求的接收者(厨师)
        LightOnCommand lightOn = new LightOnCommand(light);
        remote.setCommand(lightOn);  // 把命令传递给调用者
        remote.buttonWasPressed();  // 按下按钮
    }
}

实现遥控器


public class RemoteControl{
    Command[] onCommands;
    Command[] offCommands;
    Command undoCommand;
    public RemoteControl(){
        onCommands = new Command[7];  // 7个开按钮
        offCommands = new Command[7];  // 7个关按钮
        // 初始化为一个具体对象(该对象中的excute方法不做任何动作)
        // 这样就不需要每次都先判断onCommands[slot]是否为null再去执行excute方法
        Command noCommand = new NoCommand();  
        for(int i = 0; i < 7; i++){
            onCommands[i] = noCommand;           
            offCommands[i] = noCommand;
        }
        undoCommand = noCommand;
    }
    // 三个参数为:插槽的位置,开命令,关命令
    public void setCommand(int slot, Command onCommand, Command offCommand){
        onCommands[slot] = onCommand;
        offCommands[slot] = offCommand;
    }
    // 按下开按钮后,就开始执行一系列的动作
    public void onButtonWasPushed(int slot){
        onCommands[slot].excute();
        undoCommand = onCommands[slot];  // 按下按钮后将该操作其记录,需要撤销时可以使用
    }
    // 按下关按钮后,就开始执行一系列的动作
    public void offButtonWasPushed(int slot){
        offCommands[slot].excute();
        undoCommand = offCommands[slot];  // 按下按钮后将该操作其记录,需要撤销时可以使用
    }
    // 按下撤销按钮后,就开始执行上一个命令的一系列动作
    public void undoButtonWasPushed(int slot){
        undoCommand.undo();
    }
}
public class NoCommand implements Command{
    public void excute(){}  // 什么事都不做(可以理解为插槽上没有插入家电,但是依旧可以按下按钮)
    public void undo(){}  // 同理
}

实现命令

参考开始设计遥控器中实现打开电灯的命令


测试遥控器


public class RemoteLoader{
	public static void main(String[] args){
        RemoteControl remoteControl = new RemoteControl();
    	Light roomLight = new Light("room");
        LightOnCommand roomLightOn = new LightOnCommand(roomLight);
        LightOffCommand roomLightOff = new LightOffCommand(roomLight);
        remoteControl.setCommand(0, roomLightOn, roomLightOff);
        remoteControl.onButtonWasPushed(0);  // 使用插槽0打开卧室的灯
        remoteControl.offButtonWasPushed(0);  // 使用插槽0关闭卧室的灯
        remoteControl.undoButtonWasPushed(0);  // 按下撤销按钮,卧室灯重新打开
    }
}

一个按钮控制多个电器

假设此时想按下一个插槽0的开按钮后,同时关闭卧室灯并且打开电视,该如何实现?


// 包含一系列命令的命令
public class MarcoCommand implements Command{
    Command[] commands;
    public MarcoCommand(Command[] commands){
        this.commands = commands;
    }
    public void execute(){
        for(int i = 0; i < commands.length; i++){
            commands[i].excute();
        }
    }
    public void undo(){
        for(int i = 0; i < commands.length; i++){
            commands[i].undo();
        }
    }
}
// 具体实现 
Light roomLight = new Light("room");
TV tv = new TV("tv");
LightOffCommand roomLightOff = new LightOffCommand(roomLight);
TVOnCommand tvOn = new TVOnCommand(tv);
Commands[] roomLightOntvOff = {roomLightOff, tvOn};
MarcoCommand demo = new MarcoCommand(roomLightOntvOff);
remoteControl.setCommand(0, demo, null);

参考

Head First 设计模式-命令模式

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/44977.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

不用ps怎么修改图片?电脑图片在线处理的方法

很多小伙伴在工作、学习的时候会用到简单的图片处理工具&#xff08;在线ps 图片编辑制作工具 免费照片编辑器_压缩图&#xff09;&#xff0c;但是因为用到的功能比较多&#xff0c;需要下载安装很多电脑处理图片软件&#xff0c;非常不方便&#xff0c;而且上手比较难。下面就…

【学习笔记53】JavaScript正则表达式练习题

正则表达式练习题一、用户名、密码和手机号的验证1、案例要求2、案例分析3、HTML和CSS代码4、JS代码二、密码强度1、案例要求2、案例分析3、HTML和CSS代码4、JS代码的实现三、书写正则验证邮箱1、邮箱的验证2、代码的实现四、书写正则验证0~255的数字一、用户名、密码和手机号的…

global关键字、python实现ATM简单功能

目录 一.局部变量、全局变量 二.global关键字 演示 三.编写ATM程序 要求 详细步骤 存在问题 改进 完整代码 一.局部变量、全局变量 1.什么是局部变量 作用范围在函数内部&#xff0c;在函数外部无法使用 2.什么是全局变量 在函数内部和外部均可使用 3.如何将函数内定…

Nature子刊:精准预测分子性质和药物靶标的无监督学习框架

药品的临床疗效与安全性由在人类蛋白质组内的分子靶标决定。本文中&#xff0c;湖南大学信息科学与工程学院的李肯立/曾湘祥教授课题组提出了一种无监督的预训练深度学习框架&#xff0c;对 1000 万个未标记的类药性、生物活性分子进行预训练&#xff0c;以预测候选化合物的药物…

osgEarth示例分析——osgearth_manip

前言 本示例主要演示osgEarth的事件处理的用法&#xff0c;内容比较多&#xff0c;这部分功能也很重要。 输入命令依然采用china-simple.earth的示例&#xff0c;加上了模型&#xff0c;但是模型并没有看到&#xff0c;可能是因为模型没有放大太小的原因。在代码中设置了不加…

传奇单机架设登录器配置教程

传奇单机顾名思义就是在本地电脑上架设传奇&#xff0c;限制同一个局域网才能一起玩&#xff0c;我接触到几个朋友不明白外网和单机的区别 架设单机需要准备以下程序&#xff1a; 传奇服务端&#xff08;版本Mirserver&#xff09; DBC2000 (百度可直接下载&#xff09; 配套登…

IPv6进阶:IPv6 过渡技术之 GRE 隧道

实验拓扑 R1-R3-R2之间的网络为IPv4环境PC1及PC2处于IPv6孤岛 实验需求 R1及R2为IPv6/IPv4双栈设备在R1及R2上部署GRE隧道使得PC1及PC2能够互相访问&#xff08;先采用IPv6静态路由实现互通&#xff09;R1及R2基于建立好的GRE隧道运行OSPFv3交互IPv6路由前缀 实验步骤及配置…

【数据可视化】免费开源BI工具 DataEase 之 Tab 组件前世今生

小D &#xff1a;小助理&#xff0c;小助理&#xff0c;在哪儿呢&#xff1f;&#xff08;焦急脸&#xff09; BI 小助理&#xff1a;在呢&#xff0c;啥事&#xff1f;&#xff08;不耐烦脸&#xff09; 小D &#xff1a;又有 BI 工具放大招啦&#xff01;&#xff01;&…

C语言习题练习11--指针

1.代码结果 #include <stdio.h> int main() {int arr[] {1,2,3,4,5};short *p (short*)arr;int i 0;for(i0; i<4; i){*(pi) 0;}for(i0; i<5; i){printf("%d ", arr[i]);}return 0; } 正常&#xff1a;0001--00 02--00 03--00 04--00 05 数组内部是倒…

Kotlin高仿微信-第2篇-登录

Kotlin高仿微信-项目实践58篇详细讲解了各个功能点&#xff0c;包括&#xff1a;注册、登录、主页、单聊(文本、表情、语音、图片、小视频、视频通话、语音通话、红包、转账)、群聊、个人信息、朋友圈、支付服务、扫一扫、搜索好友、添加好友、开通VIP等众多功能。 Kotlin高仿…

【安卓逆向】去除云注入(使用MT论坛dl的方法总结拓展)

1 需求 因为最近使用的虚拟机突然不能用了&#xff0c;被人云注入强制弹窗&#xff0c;如下图&#xff1a;&#xff08;这一看就是云注入了&#xff09; 2 大佬的方法 如图&#xff08;MT大佬分享的&#xff0c;感兴趣的朋友可以去大佬主页看看他其他文章&#xff09;&…

把backtrader改造成金融强化学习回测引擎

原创文章第119篇&#xff0c;专注“个人成长与财富自由、世界运作的逻辑&#xff0c; AI量化投资”。 继续强化学习应用于金融投资。 我们的AI量化平台&#xff0c;针对传统规则量化策略&#xff0c;进行了“积木式”的拆分&#xff0c;这种拆分的好处&#xff0c;就是最大化…

【三维目标检测】Part-A2(二)

PartA2数据和源码配置调试过程请参考上一篇博文&#xff1a;【三维目标检测】Part-A2&#xff08;一&#xff09;_Coding的叶子的博客-CSDN博客。本文主要详细介绍PartA2网络结构及其运行中间状态。 1 PointRCNN模型总体过程 Part-A2的整体结构如下图所示&#xff0c;主要包括…

据2019年中国社交电商行业研究报告称,电商正处于更新换代的时期

引言&#xff1a; 据艾瑞咨询《2019年中国社交电商行业研究报告》示,传统主流电商平台用户与交易规模增速均呈现逐渐放缓的趋势,平台亟需找到更高效、低价、高粘性的流量来源,来跳出竞争日益激烈获客成本持续攀升的困境。移动互联网时代,微信、QQ、微博、快手、抖音等社交类AP…

Wordpress模板主题中functions.php常用功能代码与常用插件(持续收集整理)

用Wordpress建站的初学者一定会需要用到的Wordpress模板主题中functions.php常用功能代码与常用插件。慢慢持续收集整理....... 目录 一、Wordpress模板主题中functions文件常用的代码 二、Wordpress自定义字段的设定与调用代码&#xff08;系统常规自定义字段&#xff09; …

【面试宝典】Java八股文之Dubbo 面试题

Dubbo 面试题1、为什么要用 Dubbo?2、Dubbo 的整体架构设计有哪些分层?3、默认使用的是什么通信框架&#xff0c;还有别的选择吗?4、服务调用是阻塞的吗?5、一般使用什么注册中心?还有别的选择吗?6、默认使用什么序列化框架&#xff0c;你知道的还有哪些?7、服务提供者能…

下沉市场投资热度提升 7天酒店打造酒店投资“极致性价比”

近日&#xff0c;7天酒店 “总裁面对面”酒店投资云沙龙活动举办&#xff0c;通过微信、抖音双平台联合直播&#xff0c;多维度探讨酒店行业的“新蓝海”机遇以及下沉市场的投资模式&#xff0c;助力更多投资人把握新的市场红利。 经济型酒店拥抱“新蓝海” 下沉市场投资热度提…

【学习笔记60】JavaScript原型链的理解

一、万物皆对象 JS中, 万物都可以都可以称为对象 1、对象概念 含义1: 一种数据格式 {key: value, key2: value2}含义2: 某一类事务的实例(某一类内容中的真实个体) 2、说明 arr1就是Array这一类内容中的某一个真实个体数组也可以算作一个对象(Array 这一类事务中的一个个体) …

天宇优配|酒企没借壳!标准股份股价上演A杀,两跌停

11月28日晚间&#xff0c;接连三日大跌的规范股份&#xff08;600302.SZ&#xff09;发布股价异动公告&#xff0c;再次否定了借壳和重组风闻。当日龙虎榜该股获净卖出774.89万元&#xff0c;闻名游资“赵老哥”常用席位中国银河绍兴现身卖一席位。另外&#xff0c;也有多家本地…

五笔会消亡吗

今天第一次看到“五笔会消亡”的说法。一看好像也没有什么消不消亡的说法&#xff0c;但是深入想一想好像的确是有一个现象90 后 00后使用五笔的应该会少很多&#xff0c;可能用的非常少。 从五笔与拼音在百度的搜索比例也可以看出&#xff0c;的确在2015~2016年间有了转折&am…