博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
命令模式/command模式/行为型模式
阅读量:5155 次
发布时间:2019-06-13

本文共 2730 字,大约阅读时间需要 9 分钟。

举个栗子

指挥官向士兵下达命令,士兵执行

实现代码如下:

class Soldier {    public void exe() {        System.out.println("执行命令");    }}class Commander {    public void invok() {        Soldier soldier=new Soldier();        soldier.exe();    }}

代码问题

上诉代码是最基本的一个实现,存在问题:

  1. Commander和Soldier高度耦合
  2. 新增命令的话,要改动Commander类,扩展性不好(影响已有实现),不符合OCP原则
  3. 指挥官指挥实现多条命令时,又要改Commander
  4. 士兵执行命令时如果加一些控制的话,如记录日志、延缓执行,加到哪都不合适,SRP和OCP原则。

重构后代码

class Soldier {    public void doCommandA() {        System.out.println("执行命令A");    }    public void doCommandB() {        System.out.println("执行命令B");    }}class CommandCenterA implements Command{    Soldier soldier;    public CommandCenterA(Soldier soldier) {        this.soldier=soldier;    }        @Override    public void exe() {        waitTime();        soldier.doCommandA();        soldier.doCommandB();    }    private void waitTime() {        System.out.println("延迟执行");    }    }class Commander {    Command command;    public Commander(Command command) {        this.command=command;    }    public void exe(){        command.exe();    }}class Client{public static void main(String[] args) {    Soldier soldier=new Soldier();    Command command=new CommandCenterA(soldier);//将soldier注入到命令中心    Commander commander=new Commander(command);//将命令中心注入到指挥官    commander.exe();}

解决的问题

  1. Commander和Soldier隔离,解除耦合,
  2. 新增命令时,只需新增Command接口的实现CommandCenter,实现对命令和请求控制
  3. CommandCenter可以实现复合命令,延迟执行,记录日志等

命令模式

命令模式把一个请求或者操作封装到一个对象中,并把发出命令和执行命令隔离,使得发出命令不必关心命令如何执行。

讲个实例:

比如开关灯和开关空调。
最原始的,就是把两根电线连到一起,灯亮空调开,断开,灯灭空调关。(Receiver)
现在我们加了个开关,开关不仅能开灯,还能开空调。(将电灯开关和空调开关进一步抽象)
开关内部的实现,就是我们的命令中心。(开空调时可以设置温度,开灯时可以延缓执行)
将开关和电线隔离,并加入了我们对命令的具体控制。这就是命令模式。

Java实现要点 Invoker(请求者)+Commander(命令中心)+Receiver(执行者)

  1. 将请求者和执行者,加入中间层“命令中心”,将请求者对象绑定于一个动作
  2. 将命令中心抽象出接口,使得请求者依赖于接口而不是具体实现
  3. 命令中心实现对请求者和执行者的解耦

JDK中的命令模式

比较经典的应该就是Runnable了吧。

//执行者Runnable soldier= new Runnable() {    public void run() {        System.out.println("执行命令");    }};
//命令中心Runnable thread=new Thread(solder);//可继承Thread继续定制thread.sleep(1000);
//请求者thread.start();

Thread源码:

/* What will be run. */private Runnable target;public Thread(Runnable target) {    init(null, target, "Thread-" + nextThreadNum(), 0);}
/** * If this thread was constructed using a separate * Runnable run object, then that * Runnable object's run method is called; * otherwise, this method does nothing and returns. * 

* Subclasses of Thread should override this method. * * @see #start() * @see #stop() * @see #Thread(ThreadGroup, Runnable, String) */@Overridepublic void run() { if (target != null) { target.run(); }}

注入了Runnable,并实现了对Runnable的控制。

优点

  1. 松耦合
  2. “命令中心”对命令可控(如日志化,延缓,复合命令),对请求可控(如队列,参数化)
  3. 扩展性。只需要实现新的“命令中心”即可,任意装配,并且不影响已有的实现,因为命令发起者(指挥官)中的命令中心时接口注入。

转载于:https://www.cnblogs.com/lknny/p/5779475.html

你可能感兴趣的文章
ORA-10635: Invalid segment or tablespace type
查看>>
计算机改名导致数据库链接的诡异问题
查看>>
Windows 8 操作系统 购买过程
查看>>
软件工程课程-个人编程作业
查看>>
Java8内存模型—永久代(PermGen)和元空间(Metaspace)(转)
查看>>
ObjectiveC基础教程(第2版)
查看>>
centos 引导盘
查看>>
Notes of Daily Scrum Meeting(12.8)
查看>>
Apriori算法
查看>>
onlevelwasloaded的调用时机
查看>>
求出斐波那契数组
查看>>
Vue.js 基础学习之组件通信
查看>>
lr_start_transaction/lr_end_transaction事物组合
查看>>
每天一个Linux命令 - 【chkconfig】
查看>>
△UVA10106 - Product(大数乘法)
查看>>
golang (7) 文件操作
查看>>
关于 Object.defineProperty()
查看>>
[转] Maven 从命令行获取项目的版本号
查看>>
CodeIgniter学习笔记(四)——CI超级对象中的load装载器
查看>>
.NET CLR基本术语
查看>>