命令模式(Command pattern)-- 请求与实现的解耦

[align=center][size=x-large]PART 1 请求与实现[/size][/align]
[b]什么叫请求:[/b]用户选中一行文字,点击复制按钮,意图将文字复制到剪贴板,这个意图就叫做请求,但具体到程序中,这个请求被具象化为一个复制按钮被点击。
[b]什么叫实现:[/b]复制按钮被点击之后,引发一个操作,可能就是调用了一个方法,该方法主要实现将当前选中的内容复制到剪贴板,这个具体的操作就是实现。

[b]例如:[/b]有个记事本(notepad),记事本上面有个复制按钮(copyButton)。那么一次复制操作,就可以被分解为两步,首选是用户选中一行文字并单击复制按钮(此时触发用户想进行复制操作的请求),第二是复制操作被具体执行(也就是操作被实现了)。

文字往往描述的不如具体实践来的直白,大家想象一下选中本行文字,点击假设右边存在的“复制”按钮,此刻是不是能想象到该行已经被缓存了,可以做后面注入粘贴等等的操作了。

请求和实现,都非常直观,很容易理解。


[align=center][size=x-large]PART 2 请求与实现的耦合[/size][/align]
我们实现一个Notepad对象,顺便写了个复制和粘贴的方法。这是常见的实现方式。main函数充当一个用户去调用相应的方法,即做相应的请求。此时操作的被请求和操作的实现都是在Notepad里面耦合了。


/**
* Copyright (c) 2013 by www.futeng.org
* @{#} @Notepad.java Create on @2013-6-9 @上午11:39:18
*/
package org.futeng.pattern.command;

/**
* @author <a href="mailto:ifuteng@gmail.com">futeng</a>
*/
public class NotepadTest {

public void copy() {
System.out.println("复制当前选中文字到剪贴板...");
}

public void paste() {
System.out.println("获取剪贴板数据复制到当前光标后面...");
}
}


/**
* Copyright (c) 2013 by www.futeng.org
* @{#} @UserTest.java Create on @2013-6-9 @上午11:41:11
*/
package org.futeng.pattern.command;

/**
* @author <a href="mailto:ifuteng@gmail.com">futeng</a>
*/
public class UserTest {

public static void main(String[] args) {

NotepadTest notepadTest = new NotepadTest();

System.out.println("用户选中一行文字,点击复制按钮...");
notepadTest.copy();
System.out.println("用户将鼠标点在下一行,准备粘贴...");
notepadTest.paste();
}
}

[quote]用户选中一行文字,点击复制按钮...
复制当前选中文字到剪贴板...
用户将鼠标点在下一行,准备粘贴...
获取剪贴板数据复制到当前光标后面...[/quote]

到目前为止一切都没有问题,我们可以把复制和粘贴看成是notepad所拥有的行为。但是问题会出现在真实实现的时候,这个方法体内可就不是以行输出了,往往是拥有大量的属性甚至是状态的。一个方法是这样,一个notepad少说支持这样的操作有十几个,想想就要死人了。
怎么去解决,这里面一个关键性的key,价值连城的思维转变就是,把复制或者粘贴这个操作也当成是一个对象。那么notepad接受到复制或者粘贴的请求的时候,直接交给相应的对象去处理。那么代码的健壮性简洁性就提高了很多。
不要以为能把复制粘贴想象出作为具体对象处理不是多么了不起的事情,看看自己的代码,很肯能动辄就包含了几十个方法,很多并不是这个类在逻辑上应该能具备的功能。能细化和抽离出也是很需要业务与技术功力的。
下面看请求与实现是怎么分离的。


[align=center][size=x-large]PART 3 请求与实现的分离[/size][/align]
package org.futeng.pattern.command;

/**
* @author <a href="mailto:ifuteng@gmail.com">futeng</a>
*/
public interface Command {
public void execute();
}

package org.futeng.pattern.command;

/**
* @author <a href="mailto:ifuteng@gmail.com">futeng</a>
*/
public class CopyButtonCommand implements Command{
@Override
public void execute() {
System.out.println("复制当前选中文字到剪贴板...");
}

}

package org.futeng.pattern.command;

/**
* @author <a href="mailto:ifuteng@gmail.com">futeng</a>
*/
public class PasteButtonCommand implements Command {

@Override
public void execute() {
System.out.println("获取剪贴板数据复制到当前光标后面...");
}

}


/**
* @author <a href="mailto:ifuteng@gmail.com">futeng</a>
*/
public class Notepad {

private Command copy;
private Command paste;

public Notepad() {
this.copy = new CopyButtonCommand();
this.paste = new PasteButtonCommand();
}

public void copy() {
this.copy.execute();
}

public void paste() {
this.paste.execute();
}
}

package org.futeng.pattern.command;

/**
* @author <a href="mailto:ifuteng@gmail.com">futeng</a>
*/
public class User {
public static void main(String[] args) {
Notepad notepad = new Notepad();

System.out.println("用户选中一行文字,点击复制按钮...");
notepad.copy();
System.out.println("用户将鼠标点在下一行,准备粘贴...");
notepad.paste();
}
}

这次转变的核心思想,就是把一个方法生生抽象成一个对象了。
后面介绍一个将方法抽象对象的几个有趣应用。

[align=center][size=x-large]PART 4 批处理实现[/size][/align]
这里的批处理,理解为多个命令依次执行。可以想象一下很多绘图工具的滤镜怎么实现的。其实就是一层一层的命令加上去。例如先磨皮再调大眼睛再上色等等。这里实现一个“一键复制粘贴的功能”,其实就是将当前行复制到下一行。 :D

package org.futeng.pattern.command;

/**
* @author <a href="mailto:ifuteng@gmail.com">futeng</a>
*/
public class Notepad {

private Command copy;
private Command paste;
private Command[] batch = new Command[2];


public Notepad() {
this.copy = new CopyButtonCommand();
this.paste = new PasteButtonCommand();
this.batch[0] = this.copy;
this.batch[1] = this.paste;
}

public void copy() {
this.copy.execute();
}

public void paste() {
this.paste.execute();
}

public void copyAndPaste() {
for (Command command : this.batch) {
command.execute();
}
}
}

package org.futeng.pattern.command;

/**
* @author <a href="mailto:ifuteng@gmail.com">futeng</a>
*/
public class User {
public static void main(String[] args) {
Notepad notepad = new Notepad();

System.out.println("用户选中一行文字,直接点击一键复制粘贴按钮");
notepad.copyAndPaste();
}
}

[quote]用户选中一行文字,直接点击一键复制粘贴按钮
复制当前选中文字到剪贴板...
获取剪贴板数据复制到当前光标后面...[/quote]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值