【设计模式】——命令模式

【情景展示】

    在网络出现之前,我们的日常生活中,人与人的交际,一般使用语言沟通,然而社会在进步,随着城市化进程的加快,我们的生活发生了巨大的变化,如今的社会,人与人之间的交流方式变得多样化、多元化,例如:手机短信、微信、语音通信、视频通信、电子邮件,等等。网络拉近了人与人之间的距离,世界也因此变得越来越小,然而在交流方式增多的同时,我们会发现,其实人与人之间的语言交流变得少了,原始的东西变得少了。今天,我们重温信纸、邮局的时代。
   日常生活中的邮局,可能已经成为人们眼中的一道风景线,获取偶尔会有银行的信件催促你信用卡的到期还款日,现在已经很少有人使用信件交流传递感情。当然了,这也是社会发展的一种趋势,网络、即时通信有很多优势,为我们带来了很多便利。然而邮局作为一个发信人和收信人的中转机构,它的作用不容小觑,省去了发信人与收信人的直接交流,为发信人和收信人传递信息。
    邮局,充当着一个中间人的角色,为发信人和收信人之间建立起一个沟通的桥梁,彼此互通信息,而省去了发信人和收信人当面交流的麻烦。发信人不必知道邮局系统内部是如何运作的,信是如何发到收信人手中的,发信人所关注的就是把信交到邮局,然后等待收信人的回信。而收信人也不用关心邮局是如何吧信从一个地方运输到另一个地方,然后又通过什么样的方法找到自己,收信人关心的就是接到了发信人的信,然后回信。发信人和收信人之间就这样在邮局的中转中进行交流。
    邮局的例子,和今天分享的命令模式很相似。命令模式就是在请求者和实现者之间增加一个中间人的角色,来达到解除耦合的目的。就像发信人和收信人不是直接联系的,而是通过邮局进行通信联系。

【模式定义】

    命令模式(Command Pattern),将来自客户端的请求封装为一个对象,无须了解这个请求激活的动作或有关接受这个请求的处理细节。命令模式的根本目的在于将“请求者”与“实现者”之间解耦。其实命令模式与很多其他设计模式一样,就是在请求者和实现者之间增加一个中间人的角色,来达到解除耦合的目的。通过对中间角色的特殊设置,从而形成不同的设计模式,命令模式也不例外。命令模式正是通过一个中间的命令者角色完成请求与实现之间的解耦。

【静态建模】

发信人 —— Invoker

邮局 —— Post

收信人 —— Receiver


    发信人投递信件给邮局,邮局接到信件将信件发给收信人,整个过程就算完成。需要注意的一点是:自始至终发信人和收信人都没有任何的通信,也就是说,命令的调用者和命令的接受者是没有联系的,完全是通过中间人——邮局进行通信。

【模式实现】

工程结构图:


1、消息接收者

1.1 创建消息接收者接口——IReceiver

package com.demo.receiver;

/**
 * 信件接收者接口
 */
public interface IReceiver {

    /**
     * 收件人收到信件读取
     * @param message
     */
    public void readMail(String message);
}

1.2 创建消息接收者——Receiver

package com.demo.receiver;

/**
 * 信件接收者
 */
public class Receiver implements IReceiver{
    /**
     * 收件人收到信件读取
     * @param message
     */
    public void readMail(String message){
        System.out.println("收件人读取信件:" + message);
    }
}
2、创建中间角色邮局

2.1 邮局接口——IPost

package com.demo.command;

/**
 * 邮局接口
 */
public interface IPost {
    /**
     * 邮局发送信件
     * @param message
     */
    public void sendMail(String message);
}
2.2 邮局实现,依赖消息接收者接口——Post

package com.demo.command;

import com.demo.receiver.IReceiver;

/**
 * 邮局实现类
 */
public class Post implements IPost {

    //收件人对象实例
    private final IReceiver receiver;

    /**
     * 构造方法传入收信人对象实例
     * @param receiver
     */
    public Post(IReceiver receiver){
        this.receiver = receiver;
    }

    /**
     * 邮局发送信件
     * @param message
     */
    @Override
    public void sendMail(String message) {
        System.out.println("邮局将信件发给收件人……");
        //邮局发送信件给收信人
        this.receiver.readMail(message);
    }
}
3、消息发送者——Invoker

package com.demo.invoker;

import com.demo.command.IPost;

/**
 * 发信人
 */
public class Invoker {
    //邮局私有属性
    private IPost post;

    /**
     * 设置邮局对象实例
     * @param post
     */
    public void setPost(IPost post){
        this.post = post;
    }

    /**
     * 发信人发送信件
     * @param message
     */
    public void postMail(String message){
        System.out.println("发信人投递邮件给邮局……");
        this.post.sendMail(message);
    }
}
4、让邮局开始工作——Client

package com.demo;

import com.demo.command.IPost;
import com.demo.command.Post;
import com.demo.invoker.Invoker;
import com.demo.receiver.Receiver;

/**
 * 客户端应用程序
 */
public class Client {
    public static void main(String[] args){
       //创建一个收信人对象实例
        Receiver receiver = new Receiver();
        //创建一个邮局对象实例,传入收信人对象实例
        IPost post = new Post(receiver);
        //创建一个发信人对象实例,传入邮局对象实例
        Invoker invoker = new Invoker();
        //设置邮局
        invoker.setPost(post);
        //发信人开始发送信息!
        invoker.postMail("你好!好久不见,最近工作忙吗?");
    }
}
5、运行效果


【小结】

1、命令模式

    命令模式将一个请求封装为一个对象,从而使用户可用不同的请求对客户进行参数化;将请求排队或记录请求日志,支持可撤销的操作。命令模式的根本目的在于将“请求者”与“实现者”之间解耦。

2、设计原则

(1)“开—闭”原则:命令模式如果新增加一个具体的命令,不必修改请求的调用者,调用者就能使用具体命令,发送请求。如果新增加一个具体的命令,也不必修改具体的命令和命令接收者,新增的调用者就会使用已有的具体命令。

(2)最少知识原则:在命令模式中,请求的启动者发送命令请求给具体命令,由具体命令负责发送命令消息给命令的接收者。

3、相关的设计模式

(1)组合模式:在使用宏命令时,我们会用到组合模式。

(2)备忘录模式:可以用来存储命令的效果状态信息,用于命令的撤销和恢复功能。

(3)原型模式:可以使用原型模式(实现Cloneable接口)来负责命令。

4、使用场合

(1)抽象出待执行的动作以参数化某对象。类似过程设计中的回调机制,而命令模式正式回调机制的一个面向对象的替代品。

(2)在不同的时刻指定、排列和执行请求

(3)需要支持可撤销的操作

(4)需要支持修改日志功能。这样当系统崩溃时,这些修改可以被重做一遍。

(5)需要支持事物系统。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值