`

设计模式-------命令模式

阅读更多

重点中的重点: 把"执行者"类当中的方法变成多个命令类,这个步骤是把多个完全不同的方法变成一个统一接口,这样可以让命令接收者不用关注类中方法细节。。。厉害,把一个类中方法给统一命名啦。。。
我认为命令模式的精髓在于:增加了一个命令的管理者,为了使管理者管理命令更加方便,我们使用适配器模式统一了所有命令的接口,因为有List来接受命令,所以可以有命令队列,因为有remove();所以可以撤销命令,因为有add()我们还可以在执行的过程中动态的增加命令。。。这是他的好处,其实他与策略完全不同

/**
语义: 一个MM要命令你做事情,但是命令是不能写死的,说不定哪天他就又命令你做些新的事情。。。
技术: 既然mm命令的方法是变化的,不定的,是mm想出来的所以由mm来new 出来,然后设置给boy....
接受命令的人一定是执行命令的人


你是Client ,按键是Invoker,mp3是Receiver,播放就是一个命令Command对象,那么谁来真正执行这个命令呢? 哈哈,命令的执行者被隐藏在了Command的背后哈,被Command封装了起来----命令模式的精髓---命令的执行者被隐藏在命令的背后,与发号施令的人无关

*/
public interface command{  //这里的执行者是临时实现的,实现了execute的都是执行者(Receiver)
   public void execute();
}

public class  MM{
  	public void order(Boy b){
		Command c = new ShoppingCommand(); //注意:制造命令的人不是仅仅造出了命令,而且造出了命名的执行,其实这里mm把自己造出的命名给定义了如何执行,boy只是去按照他的方法执行而已。。。如果传递的是字符串,当然达不到这个效果,因为字符串并没有传递命令的执行本身。。。。
		b.add(c);
		b.execute();
	}
}
public class Boy {  //Invoker,他是命令的请求方,如果不用命令模式,那么Boy就是命令的执行方,
	private String name;
         //boy可以接受好多命令哦~~~~
	List<Command> commands = new ArrayList<Command>();
	
	public void add(Command c){
		commands.add(c);
	}
	
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public void execute() {
		for(Command c:commands){
			c.execute();
		}
	}
}

如果Invoker像下面这样,那么可以不需要,其实Invoker存在的意义我认为:
1.管理链式接口
2.有某种物理含义,比如上面的Boy
public class Invoker{
    private Command command;
    public void setCommand(Command command){
       this.command = command;
    }
   public void action(){
      this.command.execute();
   }
}



/*注意:扩展接口有两种方式
1.第一种,就是让那个类实现某个接口
比如:   Master impelnets Hearable

2.搞一个新的类来实现,这个和语意有关,从语文角度看。。。
一个人能做什么,那么扩展接口,
如果一个类被动接收命令,那么让命令来封装持有这个类的引用。。。。

*/
public class LightOnCommand implements Command{  //命令模式中命令的执行者
    Light light;
    public LightOnCommand(){
         this.light = light;
    }
    public void execute(){  //这里就是为了统一接口,让调用者不知节  
         light.on();
   }
}
//第二种做法的好处很明显,因为我不用去修改light这个类了,只需要把light包装一下,哈哈对修改关闭,对扩展开放就很明显了。。。。

//命令模式的扩展-----"Party"模式,所谓Party模式就是一票的命令的集合而已啦


//Java中的命令模式,如Scheduler,线程池,工作队列,想象一下你在某端添加命令,然后在另一端则是线程,线程进行下面的动作:从队列中取出一个命令,然后调用它的exectue()方法,等待这个调用完成,然后讲此命令对象丢弃,再取下一个命令。。。线程池在这里相当于Invoker,是命令的请求方,相当于Boy..........我们可以把Invoker看成是客户代理,对真正的客户来说屏蔽了细节

命令的执行者被隐藏在命令的背后,与发号施令的人无关

还有这样的Command
public abstract class Command{
   protected RequirementGroup rg = new RequirementGroup();
   protected PageGroup rg = new PagetGroup();
  protected CodeGroup rg = new CodeGroup();
   public abstract void execute();
}

public class DeletePageCommand extends Command{
    public void execute(){
         super.rg.find();
         super.rg.delete();
         super.rg.plan();
    }
}


-------------------例子二:烤羊肉串-------------------------------------------------------------
去买羊肉串,我给钱给大叔,大叔烤羊肉串,然后再给我们。。。。但有时我们却感到烤羊肉串的人经常找错钱什么的。。。这其实就是"行为请求者"与"行为实现者"的紧耦合。我们需要记录那些人要几串羊肉串,有没有特殊要求,付没付钱,谁先谁后,这其实都相当于请求做什么...对请求做记录,应该是日志,对于有人要退回请求或者要烤肉重烤,这相当于撤销和重做,所以对请求队列或者记录请求日志以及支持可撤销的操作时,请求者与行为是闲着的紧耦合是不太合适的。。。


而开店就是实现了行为请求者和行为实现者之间的解耦。。。因为服务员是这个中间层。。。
服务员根据客户需要发个命令就可以了,我们的做法是把"烤肉串这"类中地方,分别写成多个命令类,那么他们就可以被"服务员"来请求了

//抽象命令类,只需要确定"烤肉串师傅"是谁,可以看成是菜单哈
public abstract class Command{

   protected Barbecuer receiver;
   public Command(Barbecuer receiver){
        this.receiver = receiver;
   }
   abstract public void execute();
}

//烤肉串命令
class BakeMuttonCommand extends Command{
   public void execute(){
        receiver.BakeMutton();
   }
}

//烤鸡翅命令
class BakeChickenWingCommand extends Command{
   public void execute(){
        receiver.BakeChickenWing();
   }
}


//服务员类,负责接收命令,发送命令
public class Waiter{
   //private Command command;
   private List<Command> commands = new ArrayList<Command>();
   public void setOrder(Command command){
       // this.command = command;
       if("没有菜了")"请点别的菜哈";
        else commands.add(command);
   }
   //通知执行
   public void notifyBabecuer(){
      for(Command c : commands){
          c.execute();
      }
  
  //取消订单
   public void cancelOrder(Command command){
        commands.remove(command);
  }
}

命令模式将一个请求封装成一个对象,从而使你可以用不同的请求对客户端进行参数化,对请求排队或记录请求日志以及支持可撤销的操作。













分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics