第二十五讲:命令模式


package com.ibeifeng.ex1;

public class MainClass {
    public static void main(String[] args) {
        Peddler peddler = new Peddler();
        peddler.sailApple();
        peddler.sailBanana();
    }
}
package com.ibeifeng.ex1;
//小摊,小贩
/*
 * 小商贩
 * 
 */
public class Peddler {
   //卖苹果
   public void sailApple(){
       System.out.println("卖苹果");
   }
   //卖香蕉 
   public void sailBanana(){
       System.out.println("卖香蕉");
   }
}

Command:Command.

Client:MainClass

对于每一个行为都创建一个Command的实现子类:AppleCommand.

//命令类必须包含调用方,是谁在卖,是Peddler在卖.所以命令类需要持有Peddler的引用.

Invorker:执行Command对象.被调用者:Peddler,商贩被调用,所以需要持有一个Peddler的引用.


实现了使用一个专门的类Command对这种调用过程加以封装.使用命令类除了可以对以前的调用加以封装还可以添加额外的功能.

package com.ibeifeng.ex2;

public class AppleCommand extends Command{

    public AppleCommand(Peddler peddler) {
        super(peddler);
        // TODO Auto-generated constructor stub
    }

    @Override
    public void sail() {
        // TODO Auto-generated method stub
        //this.peddler.sailApple();
        this.getPeddler().sailApple();//不管你怎么搞,还是商贩在卖.
    }

}
package com.ibeifeng.ex2;

public class BananaCommand extends Command{

    public BananaCommand(Peddler peddler) {
        super(peddler);
        // TODO Auto-generated constructor stub
    }

    @Override
    public void sail() {
        // TODO Auto-generated method stub
        this.getPeddler().sailBanana();
    }

}
package com.ibeifeng.ex2;

public abstract class Command {
    private Peddler peddler;
    //protected Peddler peddler;//子类如果要直接访问peddler可以改成保护类型.
    //不必隐藏细节隐藏的那么深.并不是每个属性都是private.你只是去考虑访问权限就行了.
    public Command(Peddler peddler) {//提供一个构造函数比较方便.
        //将构造函数放在最上面,这也是我们平常的一个习惯.
        super();
        this.peddler = peddler;
    }
    public abstract void sail();
    //命令类必须包含调用方,是谁在卖,是Peddler在卖.所以命令类需要持有Peddler的引用.
    
    public Peddler getPeddler() {
        return peddler;
    }

    public void setPeddler(Peddler peddler) {
        this.peddler = peddler;
    }
    
    
}
package com.ibeifeng.ex2;

public class MainClass {
    public static void main(String[] args) {
        Peddler peddler = new Peddler();
        /*peddler.sailApple();
        peddler.sailBanana();*/
        Command appleCommand = new AppleCommand(peddler);
        Command bananaCommand = new BananaCommand(peddler);
        appleCommand.sail();
        bananaCommand.sail();//通过不同的命令来调用它的sail()方法
    }
}
package com.ibeifeng.ex2;
//小摊,小贩
/*
 * 小商贩
 * 
 */
public class Peddler {
   //卖苹果
   public void sailApple(){
       System.out.println("卖苹果");
   }
   //卖香蕉 
   public void sailBanana(){
       System.out.println("卖香蕉");
   }
}

希望有一个类Receiver.小商贩赚了一些钱了,不想自己动手了,他可以请一个服务员:waiter.帮手.

Receiver:Receiver(waiter)里面有action()方法,其实action()方法是执行Command的方法.Receiver接受一个命令.

方案二是通过命令Command的实现类调用sail()方法.所以方案三现在是由waiter来执行一个命令.所以方案三是客户跟你请的服务员直接打交道,给他发出一个命令.


package com.ibeifeng.ex3;

public class AppleCommand extends Command{

    public AppleCommand(Peddler peddler) {
        super(peddler);
        // TODO Auto-generated constructor stub
    }

    @Override
    public void sail() {
        // TODO Auto-generated method stub
        //this.peddler.sailApple();
        this.getPeddler().sailApple();//不管你怎么搞,还是商贩在卖.
    }

}
package com.ibeifeng.ex3;

public class BananaCommand extends Command{

    public BananaCommand(Peddler peddler) {
        super(peddler);
        // TODO Auto-generated constructor stub
    }

    @Override
    public void sail() {
        // TODO Auto-generated method stub
        this.getPeddler().sailBanana();
    }

}
package com.ibeifeng.ex3;

public abstract class Command {
    private Peddler peddler;
    //protected Peddler peddler;//子类如果要直接访问peddler可以改成保护类型.
    //不必隐藏细节隐藏的那么深.并不是每个属性都是private.你只是去考虑访问权限就行了.
    public Command(Peddler peddler) {//提供一个构造函数比较方便.
        //将构造函数放在最上面,这也是我们平常的一个习惯.
        super();
        this.peddler = peddler;
    }
    public abstract void sail();
    //命令类必须包含调用方,是谁在卖,是Peddler在卖.所以命令类需要持有Peddler的引用.
    
    public Peddler getPeddler() {
        return peddler;
    }

    public void setPeddler(Peddler peddler) {
        this.peddler = peddler;
    }
    
    
}
package com.ibeifeng.ex3;
//小摊,小贩
/*
 * 小商贩
 * 
 */
public class Peddler {
   //卖苹果
   public void sailApple(){
       System.out.println("卖苹果");
   }
   //卖香蕉 
   public void sailBanana(){
       System.out.println("卖香蕉");
   }
}
package com.ibeifeng.ex3;

public class Waiter {
   private Command command;

public Command getCommand() {
    return command;
}

public void setCommand(Command command) {
    this.command = command;
}

public Waiter(Command command) {
    super();
    this.command = command;
}

   public Waiter() {
    super();
    // TODO Auto-generated constructor stub
}

public void sail(){//服务员也有一个sail(),服务员也是在卖东西,是你的帮手
       command.sail();
   }
}
package com.ibeifeng.ex3;

public class MainClass {
    public static void main(String[] args) {
        Peddler peddler = new Peddler();//首先要有peddler,你要买的这个商贩/货家
        /*peddler.sailApple();
        peddler.sailBanana();*/
        Command appleCommand = new AppleCommand(peddler);//实例化Command的时候把被调用方peddler传进去
        //实际上操作的是商贩这个对象.
        Command bananaCommand = new BananaCommand(peddler);
        //appleCommand.sail();
        //bananaCommand.sail();//通过不同的命令来调用它的sail()方法
        Waiter waiter = new Waiter();//命令是由invoker(waiter)发出来的,是由它来执行这个命令.
        waiter.setCommand(appleCommand);
        waiter.sail();
        waiter.setCommand(bananaCommand);
        waiter.sail();
    }
}

Client是直接和Receiver(waiter).waiter持有了command的引用.前面讲错了,

invoker:waiter,调用者,它持有了command的引用.

Receiver:被调用者,Peddler.

调用ConcreteCommand(AppleCommand、BananaCommand)的execute()方法其实是调用了Receiver(Peddler)的Action()方法.Receiver是一个目标对象.


Command:Command.调用一个行为,被调用方是谁呢?被调用方就是Receiver(Peddler).调用ConcreteCommand的execute()方法其实是执行了Receiver(Peddler)的action()方法.Command持有的是Receiver的引用.Invoker是waiter.它持有了Command的引用.

命令是发到invoker,也就是这个waiter.是由waiter来执行这个命令.

建类的顺序也是Peddler->Command->Waiter,客户端MainClass调用的顺序也是这样的一层一层.和现实生活的例子逻辑相反,客户直接和waiter交互,要买什么商家(Receiver(Peddler))的商品,发送不同的命令(比如说AppleCommand这个命令),waiter接受并执行客户的命令(比如说AppleCommand这个命令(封装了目标对象Receiver(Peddler)的行为:卖苹果),调用了AppleCommand的sail()方法,AppleCommand的sail()方法其实是调用了peddler的sailApple()方法.如果是BananaCommand这个命令,waiter就调用BananaCommand的sail()方法,调用BananaCommand的sail()方法其实是调用peddler的sailBanana()方法.

Pedder和Command可以创建在一起,但是setCommand()的时候必须把Command的实现类添加进去.


最终版的命令模式:invoker(waiter)其实是包含很多命令类,命令类是作用于Receiver(peddler)的action方法.


package com.ibeifeng.ex4;

public class AppleCommand extends Command{

    public AppleCommand(Peddler peddler) {
        super(peddler);
        // TODO Auto-generated constructor stub
    }

    @Override
    public void sail() {
        // TODO Auto-generated method stub
        //this.peddler.sailApple();
        this.getPeddler().sailApple();//不管你怎么搞,还是商贩在卖.
    }

}
package com.ibeifeng.ex4;

public class BananaCommand extends Command{

    public BananaCommand(Peddler peddler) {
        super(peddler);
        // TODO Auto-generated constructor stub
    }

    @Override
    public void sail() {
        // TODO Auto-generated method stub
        this.getPeddler().sailBanana();
    }

}
package com.ibeifeng.ex4;

public abstract class Command {
    private Peddler peddler;
    //protected Peddler peddler;//子类如果要直接访问peddler可以改成保护类型.
    //不必隐藏细节隐藏的那么深.并不是每个属性都是private.你只是去考虑访问权限就行了.
    public Command(Peddler peddler) {//提供一个构造函数比较方便.
        //将构造函数放在最上面,这也是我们平常的一个习惯.
        super();
        this.peddler = peddler;
    }
    public abstract void sail();
    //命令类必须包含调用方,是谁在卖,是Peddler在卖.所以命令类需要持有Peddler的引用.
    
    public Peddler getPeddler() {
        return peddler;
    }

    public void setPeddler(Peddler peddler) {
        this.peddler = peddler;
    }
    
    
}
package com.ibeifeng.ex4;

public class MainClass {
    public static void main(String[] args) {
        Peddler peddler = new Peddler();//首先要有peddler,你要买的这个商贩/货家
        /*peddler.sailApple();
        peddler.sailBanana();*/
        Command appleCommand = new AppleCommand(peddler);//实例化Command的时候把被调用方peddler传进去
        //实际上操作的是商贩这个对象.
        Command bananaCommand = new BananaCommand(peddler);
        //appleCommand.sail();
        //bananaCommand.sail();//通过不同的命令来调用它的sail()方法
        Waiter waiter = new Waiter();//命令是由invoker(waiter)发出来的,是由它来执行这个命令.
        //waiter.setCommand(appleCommand);
        //下订单
        waiter.setOrder(appleCommand);
        //waiter.sail();
        //waiter.setCommand(bananaCommand);
        waiter.setOrder(bananaCommand);
        
        //移除订单某项
        waiter.removeOrder(bananaCommand);
        waiter.sail();
    }
}
package com.ibeifeng.ex4;
//小摊,小贩
/*
 * 小商贩
 * 
 */
public class Peddler {
   //卖苹果
   public void sailApple(){
       System.out.println("卖苹果");
   }
   //卖香蕉 
   public void sailBanana(){
       System.out.println("卖香蕉");
   }
}
package com.ibeifeng.ex4;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Waiter {
   //private Command command;
    private List<Command> commands = new ArrayList<Command>();//订单,菜单,菜谱

/*public Command getCommand() {
    return command;
}*/
public void sail(){
    for (Command command :  commands){
        command.sail();
    }
}
//public void setCommand(Command command) {
public void setOrder(Command command) {
    //this.command = command;
    commands.add(command);
}
public void removeOrder(Command command){
    commands.remove(command);
}
/*public Waiter(Command command) {
    super();
    this.command = command;
}*/

/*   public Waiter() {
    super();
    // TODO Auto-generated constructor stub
}*/

/*public void sail(){//服务员也有一个sail(),服务员也是在卖东西,是你的帮手
       command.sail();
   }*/
}
原文地址:https://www.cnblogs.com/ZHONGZHENHUA/p/6755531.html