命令模式

命令模式

一、简介

定义:将一个请求封装成一个对象,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。

二、使用场景

在某些场合,比如需要对行为进行记录、撤销或重做、事务等处理时可以使用命令模式

三、简单实现

以实现一个简单的绘图板为例。

//抽象触笔类
public interface IBrush{
    void down(Path path, float x, float y);
    void up(Path path,float x,float y);
    void move(Path path,float x,float y);
}

public class NormalBrush implements IBrush{

    @Override
    public void down(Path path, float x, float y) {
     path.moveTo(x,y);
    }

    @Override
    public void up(Path path, float x, float y) {

    }

    @Override
    public void move(Path path, float x, float y) {
     path.lineTo(x,y);
    }
}

public class CircleBrush implements IBrush{

    @Override
    public void down(Path path, float x, float y) {

    }

    @Override
    public void up(Path path, float x, float y) {

    }

    @Override
    public void move(Path path, float x, float y) {
      path.addCircle(x,y,10,Path.Direction.CW);
    }
}

//命令接口
public interface IDraw{
    void draw(Canvas canvas);
    void undo();
}

public class DrawPath implements IDraw{
    public Path path;
    public Paint paint;
    @Override
    public void draw(Canvas canvas) {
      canvas.drawPath(path,paint);
    }

    @Override
    public void undo() {

    }
}

//请求者
public class Invoker{
    //绘制列表
    private List<DrawPath> drawPathList= Collections.synchronizedList(new ArrayList<>());
    //重做列表
    private List<DrawPath> redoPathList= Collections.synchronizedList(new ArrayList<>());

    public void add(DrawPath command){
        redoPathList.clear();
        drawPathList.add(command);
    }

    public void undo(){
        if (drawPathList.size()>0){
            DrawPath undo=drawPathList.get(drawPathList.size()-1);
            drawPathList.remove(drawPathList.size()-1);
            undo.undo();
            redoPathList.add(undo);
        }
    }

    public void redo(){
        if (redoPathList.size()>0){
            DrawPath redo=redoPathList.get(redoPathList.size()-1);
            redoPathList.remove(redoPathList.size()-1);
            drawPathList.add(redo);
        }
    }

    public void execute(Canvas canvas){
        if (drawPathList!=null){
            for (DrawPath drawPath : drawPathList) {
                drawPath.draw(canvas);
            }
        }
    }

    public  boolean canRedo(){
        return redoPathList.size()>0;
    }

    public boolean canUndo(){
        return drawPathList.size()>0;
    }

}

public void main(){
    Invoker invoker=new Invoker();
    invoker.add(new DrawPath());
    invoker.redo();
    
}

四、小结

命令模式并不局限于GUI在很多地方都可以使用,比如在onClick方法中使用分支语句来处理不同按钮的点击事件,这时候如果每个分支的逻辑很复杂就可以使用命令模式,一个分支对应一条命令以增强代码可读性。

命令模式的缺点是会产生大量的类。

posted @ 2020-10-10 20:00  Robin132929  阅读(75)  评论(0编辑  收藏  举报