示例场景
代码语言:javascript复制// 接收者
public interface SonReceiver {
public void pay(int money); // 交保护费
public void bite(boolean b); // 咬人
public void build(boolean b); // 军事基地建设
}
public class GuiZi implements SonReceiver {
public void pay(int money) {
System.out.println("上交保护费 " money);
}
public void bite(boolean b) {
if (b) {
System.out.println("朝向东方某国竖中指,放狠话");
} else {
System.out.println("朝向东方某国,握手,我们是好朋友");
}
}
public void build() {
System.out.println("基地建设要不要放缓");
}
}
public class BangZi implements SonReceiver {
public void pay(int money) {
System.out.println("上交保护费 " money);
}
public void bite(boolean b) {
if (b) {
System.out.println("朝向东方某国,汪,汪汪");
} else {
System.out.println("朝向东方某国,喵,喵喵");
}
}
public void build(boolean b) {
System.out.println("基地建设要不要放缓 " b);
}
}
public class FatherDengTa {
// 需要鞭策儿子了
public void shouGuiZiBHF() {
GuiZi gz = new GuiZi();
gz.pay(5);
gz.bite(false);
gz.build(false);
}
public void shouBangZiBHF() {
BangZi bz = new BangZi();
bz.pay(1);
bz.bite(true);
bz.build(true);
}
}
在例子中,爸爸亲自下场,和儿子要钱,爸爸只想要钱这么一个结果。
但是儿子一看要的有点多,就和爸爸商量你这有点狠啊,那我是不是得缓和一下和东方某国的关系,这样能多赚点钱,爸爸一听说也行,儿子又说,要缓和关系,那咱军事基地就得缓一缓,不能刺激人家,爸爸一听毛了,那不行,算了,那钱少收点,儿子说那成,我继续咬东方某国。
命令模式1.png
这样一件一件事来谈,会很繁琐,爸爸很忙,哪里有时间管这么多事。
中介者模式改造
所以想着也抽出一个中介,通过中介去做。和中介者模式感觉有那么一点像,但中介者是两两有交互,形成一个网状结构,是类间横向有关系,所以抽出一个中介者,变成星形状。这里像是类内点纵向关系,是一个方法就引起其它方法变化。
中介者模式.png
爸爸不想管了,爸爸说我不管这么多了,我就给你一个命令:交钱,你自己掂量。先类似中介的方法改造。
代码语言:javascript复制// 就不写抽象了
public class Mediator {
private GuiZi gz = new GuiZi();
private BangZi bz = new BangZi();
public void execute(String str,Object...objects){
if (str.equals("guiZi.pay")) {
gz.pay((int)objects[0]); // 假设交得太多了
gz.bite(false);
gz.build(false);
} else if (str.equals("bangZi.pay")) {
bz.pay((int)objects[0]); // 交得不是很多
bz.bite(true);
bz.build(true);
}
}
}
public class FatherDengTa() {
private Mediator mediator;
public FatherDengTa(Mediator _mediator){
this.mediator = mediator;
}
public void shouGuiZiBHF() {
mediator.execute("guiZi.pay", 5)
}
public void shouBangZiBHF() {
mediator.execute("bangZi.pay", 1)
}
}
public class GuiZi {
private Mediator mediator;
public GuiZi(Mediator _mediator){
this.mediator = mediator;
}
public void pay(int money) {
System.out.println("上交保护费 " money);
}
public void bite(boolean b) {
if (b) {
System.out.println("朝向东方某国竖中指,放狠话");
} else {
System.out.println("朝向东方某国,握手,我们是好朋友");
}
}
public void build() {
System.out.println("基地建设要不要放缓");
}
}
失败了,因为 GuiZi 作为底层的,不需要和其它交流,中介者给它也用不着。
命令模式改造
将命令封装成 Command,Command 本身就能明确哪个接收者该做什么事情。
代码语言:javascript复制public abstract class Command {
protected int money;
public Command(int money) {
this.money = money;
}
//接收者定义好
protected GuiZi gz = new GuiZi();
protected BangZi bz = new BangZi();
// 只有一个执行方法
public abstract void execute();
}
// 一个具体的命令本身,既能表明接收者是谁,又能表明需要做什么
public GuiZiPayCommand extends Command {
public GuiZiPayCommand(int money) {
super(money);
}
public void execute() {
gz.pay(money);
gz.bite(false);
gz.build(false);
}
}
// 类似中介,负责接收高层的命令,负责执行命令,命令一旦执行,就到了底层的接收者了
public class Invoker {
private Command cmd;
public void setCommand(Command command) {
cmd = command;
}
public void action() {
cmd.execute();
}
}
public class FatherDengTa() {
private Invoker invoker = new Invoker(); // 中介
public void shouGuiZiBHF() {
Command cmd = new GuiZiPayCommand(5);
invoker.setCommand(cmd);
invoker.action();
}
}
命令模式2.png
特点
- 解耦,爸爸只需要把命令给执行者 Invoker,Invoker 只需要执行 Command,具体的逻辑都封装到 Command 内部去了。
- 方便扩展,多一件事情,只需要创建一个命令,修改命令对象的引用,其它都不需要改
- 当交互对象多了后,中介者会越大越复杂,这里也是,如果要做的事情多了后,每个都需要定义一个 Command,会越来越多,甚至感觉太细碎。