[8] [行为变化] ( 1 ) 命令模式 command

总结

  • GOF定义?
    将一个请求(行为)封装为一个对象,
    从而使你可用不同的请求对客户进行参数化操作.
    比如请求排队, 记录请求日志, 撤销...
    (请求一旦变成对象就具有了很高的灵活度)


  • 该模式的目的是什么?
    解耦 Invoker请求方 和 Receiver行为实现者
    (RemoteControl 和 Light子类)


  • 如何达成目的?
    把行为封装成对象
    (把Receiver行为实现者封装成Command对象)


  • 命令模式的优点?
    请求(行为)可以被更灵活的处理
    (1) 当做方法参数传递
    (2) 延迟执行
    (3) 排队执行
    (4) 可撤销操作


  • 场景举例?
    文本编辑器
    图形编辑器


  • Command模式和c++函数对象的区别?
    Command模式是运行时多态. (通过接口规范实现, 更加严格, 但虚函数有性能损失)
    C++函数对象是编译时多态. (通过模板实现的泛型编程, 性能更好)


  • 补充参考资料
    https://blog.csdn.net/A_art_xiang/article/details/130706288




java例子

重构前

Invoker请求方(LightController1)和Receiver行为实现者(Light子类)紧耦合.

package v23_command.java;

interface Light {
    void on();
    void off();
}

class LivingRoomLight implements Light {
    public void on() {
        System.out.println("Living room light is on");
    }

    public void off() {
        System.out.println("Living room light is off");
    }
}

class KitchenLight implements Light {
    public void on() {
        System.out.println("Kitchen light is on");
    }

    public void off() {
        System.out.println("Kitchen light is off");
    }
}

public class LightController1 {
    public static void main(String[] args) {
        LivingRoomLight livingRoomLight = new LivingRoomLight();
        KitchenLight kitchenLight = new KitchenLight();

        kitchenLight.on();
        kitchenLight.off();
        livingRoomLight.on();
        livingRoomLight.off();
    }
}



重构后

package v23_command.java;

import java.util.Arrays;
import java.util.List;


interface Light {
    void on();

    void off();

    void increaseBrightness();
}


class KitchenLight implements Light {
    public void on() {
        System.out.println("Kitchen light is on");
    }

    public void off() {
        System.out.println("Kitchen light is off");
    }

    public void increaseBrightness() {
        System.out.println("Kitchen light brightness increased");
    }
}


class LivingRoomLight implements Light {
    public void on() {
        System.out.println("Living room light is on");
    }

    public void off() {
        System.out.println("Living room light is off");
    }

    public void increaseBrightness() {
        System.out.println("Living room light brightness increased");
    }
}


interface Command {
    void execute();

    void undo();
}


class LightOnCommand implements Command {
    private Light light;

    public LightOnCommand(Light light) {
        this.light = light;
    }

    public void execute() {
        light.on();
    }

    public void undo() {
        light.off();
    }
}


class LightOffCommand implements Command {
    private Light light;

    public LightOffCommand(Light light) {
        this.light = light;
    }

    public void execute() {
        light.off();
    }

    public void undo() {
        light.on();
    }
}


class LightIncreaseCommand implements Command {
    private Light light;

    public LightIncreaseCommand(Light light) {
        this.light = light;
    }

    public void execute() {
        light.increaseBrightness();
    }

    public void undo() {
        // Implement an appropriate undo operation, such as decreasing brightness
        System.out.println("TODO");
    }
}


class Fan {
    public void on() {
        System.out.println("Fan is on");
    }

    public void off() {
        System.out.println("Fan is off");
    }
}


class FanOnCommand implements Command {
    private Fan fan;

    public FanOnCommand(Fan fan) {
        this.fan = fan;
    }

    public void execute() {
        fan.on();
    }

    public void undo() {
        fan.off();
    }
}


class AllLightsOffCommand implements Command {
    private List<Light> lights;

    public AllLightsOffCommand(List<Light> lights) {
        this.lights = lights;
    }

    public void execute() {
        for (Light light : lights) {
            light.off();
        }
    }

    public void undo() {
        for (Light light : lights) {
            light.on();
        }
    }
}


class RemoteControl {
    private Command command;

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

    public void pressButton() {
        command.execute();
    }

    public void pressUndo() {
        command.undo();
    }
}


public class LightController3 {
    public static void main(String[] args) {
        LivingRoomLight livingRoomLight = new LivingRoomLight();
        KitchenLight kitchenLight = new KitchenLight();
        Fan fan = new Fan();

        LightOnCommand livingRoomLightOn = new LightOnCommand(livingRoomLight);
        LightOffCommand kitchenLightOff = new LightOffCommand(kitchenLight);
        LightIncreaseCommand kitchenLightIncrease = new LightIncreaseCommand(kitchenLight);
        FanOnCommand fanOn = new FanOnCommand(fan);
        AllLightsOffCommand allLightsOff = new AllLightsOffCommand(Arrays.asList(
                    livingRoomLight, kitchenLight));

        RemoteControl remote = new RemoteControl();

        remote.setCommand(livingRoomLightOn);
        remote.pressButton(); // Living room light is on
        remote.pressUndo(); // Living room light is off

        remote.setCommand(kitchenLightOff);
        remote.pressButton(); // Kitchen light is off
        remote.pressUndo(); // Kitchen light is on

        remote.setCommand(kitchenLightIncrease);
        remote.pressButton(); // Increase kitchen light brightness

        remote.setCommand(fanOn);
        remote.pressButton();

        remote.setCommand(allLightsOff);
        remote.pressButton();
    }
}





image




image




java例子2


package v23_command.java;
import java.util.Stack;

interface Command {
   void execute();
   void undo();
}

class InsertTextCommand implements Command {
   private String textToInsert;
   private StringBuilder textEditor;
   private int position;

   public InsertTextCommand(String text, StringBuilder editor, int position) {
		 this.textToInsert = text;
		 this.textEditor = editor;
		 this.position = position;
   }

   @Override
   public void execute() {
	   textEditor.insert(position, textToInsert);
   }

   @Override
   public void undo() {
	   textEditor.delete(position, position + textToInsert.length());
   }
}

class DeleteTextCommand implements Command {
   private String deletedText;
   private StringBuilder textEditor;
   private int position;

   public DeleteTextCommand(StringBuilder editor, int position, int length) {
	   this.textEditor = editor;
	   this.position = position;
	   this.deletedText = textEditor.substring(position, position + length);
   }
   
   @Override
   public void execute() {
	   textEditor.delete(position, position + deletedText.length());
   }

   @Override
   public void undo() {
	   textEditor.insert(position, deletedText);
   }
}

class CommandInvoker {
	Stack<Command> commandStack = new Stack<>();
	Stack<Command> undoStack = new Stack<>();

	public void execute(Command command) {
		command.execute();
		commandStack.push(command);
	}

	public void undo() {
		if (!commandStack.isEmpty()) {
			Command command = commandStack.pop();
			command.undo();
			undoStack.push(command);
		}
	}

	public void redo() {
		if (!undoStack.isEmpty()) {
			Command command = undoStack.pop();
			command.execute();
			commandStack.push(command);
		}
	}
}

public class TextEditor {
   public static void main(String[] args) {
	   // Initialize the text editor and invoker
	   StringBuilder textEditor = new StringBuilder();
	   CommandInvoker invoker = new CommandInvoker();

	   // Insert "Hello, "
	   invoker.execute(new InsertTextCommand("Hello, ", textEditor, 0));

	   // Insert "world!"
	   invoker.execute(new InsertTextCommand("world!", textEditor, 7));

	   // Delete ", "
	   invoker.execute(new DeleteTextCommand(textEditor, 5, 2));

	   // Current text should be "Helloworld!"
	   System.out.println("Current text: " + textEditor.toString());

	   invoker.undo(); // Undo delete - should be back to "Hello, world!"
	   System.out.println("After undo: " + textEditor.toString());

	   invoker.undo(); // Undo last insert - should be back to "Hello, "
	   System.out.println("After undo: " + textEditor.toString());

	   invoker.redo(); // Redo last insert - should be back to "Hello, world!"
	   System.out.println("After redo: " + textEditor.toString());
   }
}





image




posted @ 2023-12-09 02:46  qwertzxc  阅读(17)  评论(0)    收藏  举报