zoukankan      html  css  js  c++  java
  • 命令模式

    参考:http://blog.csdn.net/fatherican/article/details/44966891

    依赖关系(Dependence)

    依赖关系(Dependence):假设A类的变化引起了B类的变化,则说名B类依赖于A类。

     在UML中,依赖关系用带箭头的虚线表示,由依赖的一方指向被依赖的一方。

     

    public class Driver
    {
      public void drive(Car car)
      {
        car.move();
      }
      ……
    }
    public class Car
    {
      public void move()
      {
        ......
      }
      ……
    }

    依赖关系有如下三种情况:

    1、A类是B类中的(某中方法的)局部变量;

    2、A类是B类方法当中的一个参数;

    3、A类向B类发送消息,从而影响B类发生变化;

    -------------------------------------------------------------------------------------------------------------------

    oo原则:

    封装变化

    多用组合,少用继承

    针对接口编程,不针对实现编程

    为交互对象之间松耦合设计而努力

    类应该对扩展开放,对修改关闭

    依赖抽象,不要依赖具体类

    ------------------------------------------------------------------------------------------------------

    命令模式:

    发出请求的对象 和 执行请求的对象 解耦。

    两者之间通过命令对象进行沟通。

    命令可以撤销,方法是:实现接口的undo()方法

    宏命令是命令的一种简单延伸,允许调用多个命令。

    命令模式的用途:队列请求,实现日志和事物系统。

    伪代码:

    //执行者
    public class Light{
    
        public void on()
        {
            //打开...
        }
        
        public void off()
        {
            //关闭....
        }
    }
    
    //接口
    public interface Command
    {
        public void execute();
        public void undo();
    }
    
    //命令对象
    public class LightOnCommand implements Command
    {
        Light light;
        
        public LightOnCommand(Light light)
        {
            this.light = light;
        }
        
        public void execute()
        {
            light.on();
        }
        
        public void undo()
        {
            light.off();
        }
    }
    
    
    //需要判断命令是否加载了
    public void onButtonWasPushed(int slot)
    {
        if(OnCommands[slot] != null)
        {
            OnCommands[slot].execute();
        }
    }
    //实现一个不做任何事情的命令。避免每次判断是否加载了命名
    public class NoCommand implements Command
    {
        public void execute()
        {    
        }
        
        public void undo()
        {    
        }
    }
    NoCommand对象是一个空对象(null object)的例子。当你不想返回一个有意义的对象时,空对象
    就很有用。在许多设计模式中,都会看到空对象的使用。甚至有些时候,空对象本身也被视为是一种
    设计模式。
    
    
    
    
    //批量命令执行
    public class MacroCommand implements Command
    {
        Command[] commands;
        
        public MacroCommand(Command[] commands)
        {
            this.commands = commands;
        }
        
        public void execute()
        {
            for(int i=0;i<commands.length;i++)
            {
                commands[i].execute();
            }
        }
        
        public void undo()
        {
            for(int i=0;i<commands.length;i++)
            {
                commands[i].undo();
            }
        }
        
    }
    
    //调用者
    public class RemoteCtrl{
        Command[] OnCommands;
        Command[] OffCommands;
        Command undoCommand;//撤销
        
        public RemoteCtrl()
        {
            OnCommands = new Command[7];
            OffCommands = new Command[7];
            
            Command noCommand = new Command();
            for(int i=0;i<7;i++)
            {
                OffCommands[i] = noCommand;
                OnCommands[i] = noCommand;
            }
            undoCommand = noCommand;
        }
        
        public void setCommand(int slot, Command onCommand, Command offCommand)
        {
            OnCommands[slot] = onCommand;
            OffCommands[slot] = offCommand;
        }
        
        public void onButtonWasPushed(int slot)
        {
            OnCommands[slot].execute();
            undoCommand = OnCommands[slot];
        }
        
        public void offButtonWasPushed(int slot)
        {
            OffCommands[slot].execute();
            undoCommand = OffCommands[slot];
        }
        
        public void undoButtonWasPushed(int slot)
        {
            undoCommand.undo();
        }
        
        
    }
    
    --------------------------------------------------------------------
    
    
    
    //初始化设置
    public class RemoteLoader
    {
    
        public static void main(String[] args)
        {
            //调用者
            RemoteCtrl remoteCtrl = new RemoteCtrl();
            
        
            //执行者
            Light light     = new Light("Bedroom");
            Tv    tv        = new Tv("Living room");
            Stereo stereo     = new Stereo("Living room");
            HotTub hutTub   = new HotTub("Hot tub");
    
            //命令对象
            OnCommandLigth lightOn = new OnCommandLigth(light);
            OnCommandTv       tvOn = new OnCommandTv(tv);
            OnCommandStereo stereoOn = new OnCommandStereo(stereo);
            OnCommandHotTub    hotTubOn = new OnCommandHotTub(hutTub);
    
            //命令对象
            OffCommandLigth    lightOff  = new OffCommandLigth(light);
            OffCommandTv       tvOff     = new OffCommandTv(tv);
            OffCommandStereo   stereoOff = new OffCommandStereo(stereo);
            OffCommandHotTub   hotTubOff = new OffCommandHotTub(hutTub);
    
            //批量命令
            Command[] partyOn = {lightOn, tvOn, stereoOn, hotTubOn};
            Command[] partyOff = {lightOff, tvOff, stereoOff, hotTubOff};
            
            //命令对象
            MacroCommand onMacroCommand = new MacroCommand(partyOn);
            MacroCommand offMacroCommand = new MacroCommand(partyOff);
            
            
            remoteCtrl.setCommand(0, onMacroCommand, offMacroCommand);
            
            remoteCtrl.setCommand(1, lightOn, lightOff);
            
            remoteCtrl.setCommand(2, tvOn, tvOff);
            
            remoteCtrl.setCommand(3, stereoOn, stereoOff);
            
            remoteCtrl.setCommand(4, hotTubOff, hotTubOff);
            
            
            //测试
            remoteCtrl.onButtonWasPushed(1);//打开电灯
            remoteCtrl.offButtonWasPushed(1);//关闭电灯
            remoteCtrl.undoButtonWasPushed(1);//撤销操作,执行打开电灯
            
            remoteCtrl.onButtonWasPushed(2);//打开电视
            remoteCtrl.offButtonWasPushed(2);//关闭电视
            
    
            
        }
    
    }
    
    
    
    //使用状态实现撤销
    通常实现撤销的功能,需要记录一些状态。比方说吊扇,吊扇允许有多种转速,当然也允许被关闭。
    public class CeilingFan{
        public static final int HIGH = 3;
        public static final int MEDIUM = 2;
        public static final int LOW = 1;
        public static final int OFF = 0;
        String location;
        int speed;
        
        public CeilingFan(String location)
        {
            this.location = location;
            speed = OFF;
        }
        
        public void high()
        {
            speed = HIGH;
            
            //设置高转速
        }
        
        public void medium()
        {
            speed = MEDIUM;
            
            //...
        }
        
        public void low()
        {
            speed = LOW;
            
            //...
        }
        
        public void off()
        {
            speed = OFF;
            
            //...
        }
        
        //风扇当前的档位
        public int getSpeed()
        {
            return speed;
        }
    
    }
    
    public class CeilingFanHighCommand implements Command{
        CeilingFan ceilingFan;
        int preSpeed;
        
        public CeilingFanHighCommand(CeilingFan ceilingFan)
        {
            this.ceilingFan = ceilingFan;
        }
        
        public void execute()
        {
            preSpeed = ceilingFan.getSpeed();
            ceilingFan.high();
        }
        
        public void undo()
        {
            if(preSpeed == CeilingFan.HIGH)
            {
                ceilingFan.high();
            }
            else if(preSpeed == CeilingFan.MEDIUM)
            {
                ceilingFan.medium();
            }
            else if(preSpeed == CeilingFan.LOW)
            {
                ceilingFan.low();
            }
            else if(preSpeed == CeilingFan.OFF)
            {
                ceilingFan.off();
            }
            
        }
    
    }
    
    -------------------------------------
    后记:
    实际操作时,很常见使用“聪明”命令对象,也就是直接实现了
    请求,而不是将工作委托给接收者。
    
    实现多层撤销:不要只是记录最后一个被执行的命令,而使用一个堆栈记录操作
    过程的每一个命令。然后,不管什么时候按下了撤销按键,都可以从堆栈中取出最上层的
    命令,然后调用它的undo方法。
    
    
    
    
    
    
    
    
    
      

     

  • 相关阅读:
    flex+spring3.0+blazds 数据推送整理版
    深入理解java虚拟机学习笔记1.
    一个netty序列化引起的思考。
    万年历
    面试理论题
    EF之Database First
    20120902 09:29 SQL、LINQ、Lambda 三种用法
    内容漂浮在图片上(div漂浮)
    生成订单号
    时间对比
  • 原文地址:https://www.cnblogs.com/zhangxuan/p/8304028.html
Copyright © 2011-2022 走看看