设计模式之命令模式(Command Pattern)

来源:互联网 发布:网络布局要看什么书籍 编辑:程序博客网 时间:2024/05/16 02:26

命令模式主要通过中介Command实现了发出命令者和命令的执行者,也即Invoke类和Receiver的松耦合。
先看类图:
这里写图片描述
将请求封装成一个对象,从而使用户使用不同的请求把客户端参数化,请求队列或者记录日志,以及支持可撤销的操作。
看一个Android的例子
先定义两种画笔,这里是额外的,也就是说更这个设计模式没有太多关系,只是程序需要:

package com.example.yale.mydrawbrush.Brush;import android.graphics.Path;/** * Created by Yale on 16/7/8. *///抽象笔触public interface IBrush {    /**     * 触点接触时     * @param path     * @param x     * @param y     */    void down(Path path, float x, float y);    /**     * 触点移动式     * @param path     * @param x     * @param y     */    void move(Path path, float x, float y);    /**     * 触点离开时     * @param path     * @param x     * @param y     */    void up(Path path, float x, float y);}

普通触笔

package com.example.yale.mydrawbrush.Brush;import android.graphics.Path;/** * Created by Yale on 16/7/8. */public class NormalBrush implements IBrush {    @Override    public void down(Path path, float x, float y) {        path.moveTo(x, y);    }    @Override    public void move(Path path, float x, float y) {        path.lineTo(x, y);    }    @Override    public void up(Path path, float x, float y) {    }}

圆形触笔

package com.example.yale.mydrawbrush.Brush;import android.graphics.Path;/** * Created by Yale on 16/7/8. */public class CircleBrush implements IBrush {    @Override    public void down(Path path, float x, float y) {    }    @Override    public void move(Path path, float x, float y) {        path.addCircle(x, y, 10, Path.Direction.CW);    }    @Override    public void up(Path path, float x, float y) {    }}

下面关键来了,我们先定义抽象命令接口,也就是绘制命令接口:

package com.example.yale.mydrawbrush.Brush;/** * Created by Yale on 16/7/8. */import android.graphics.Canvas;/** * 对于每一次路径绘制,有两个命令:绘制命令和撤销命令 */public interface IDraw {    /**     * 绘制命令     * @param canvas 画布对象     */    void draw(Canvas canvas);    /**     * 撤销命令     */    void undo();}

具体的绘制命令,也就是实现上面的接口

package com.example.yale.mydrawbrush.Brush;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.Path;/** * Created by Yale on 16/7/8. */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() {    }}

然后是命令的发出者Invoker,定义为DrawInvoker

package com.example.yale.mydrawbrush.Brush;import android.graphics.Canvas;import java.util.ArrayList;import java.util.Collections;import java.util.List;/** * Created by Yale on 16/7/8. */public class DrawInvoker {    //绘制列表    private List<DrawPath> drawList = Collections.synchronizedList(new ArrayList<DrawPath>());    //重做列表    private List<DrawPath> redoList = Collections.synchronizedList(new ArrayList<DrawPath>());    public void add(DrawPath command) {        redoList.clear();        drawList.add(command);    }    public void undo() {        if (drawList.size() > 0) {            DrawPath undo = drawList.get(drawList.size() - 1);            drawList.remove(drawList.size() - 1);            undo.undo();            redoList.add(undo);        }    }    public void redo() {        if (redoList.size() > 0) {            DrawPath redoCommand = redoList.get(redoList.size() - 1);            redoList.remove(redoList.size() - 1);            drawList.add(redoCommand);        }    }    public void execute(Canvas canvas) {        if (drawList != null) {            for (DrawPath temp : drawList) {                temp.draw(canvas);            }        }    }    public boolean canRedo() {        return redoList.size() > 0;    }    public boolean canUndo() {        return drawList.size() > 0;    }}

再定义命令的执行者,也就是Receiver,这里定义为DrawCanvas

package com.example.yale.mydrawbrush.Brush;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.PorterDuff;import android.util.AttributeSet;import android.view.SurfaceHolder;import android.view.SurfaceView;/** * Created by Yale on 16/7/8. */public class DrawCanvas extends SurfaceView  implements SurfaceHolder.Callback{    public boolean isDrawing, isRunning;    private Bitmap mBitmap;    private DrawInvoker mInvoker;    private DrawThread mThread;    public DrawCanvas(Context context, AttributeSet attrs) {        super(context, attrs);        mInvoker = new DrawInvoker();        mThread = new DrawThread();        getHolder().addCallback(this);    }    public void add(DrawPath path){        mInvoker.add(path);    }    public void redo(){        isDrawing = true;        mInvoker.redo();    }    public void undo(){        isDrawing = true;        mInvoker.undo();    }    public boolean canUndo(){        return mInvoker.canUndo();    }    public boolean canRedo(){        return mInvoker.canRedo();    }//    @Override    public void surfaceCreated(SurfaceHolder surfaceHolder) {        isRunning = true;        mThread.start();    }//    @Override    public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height) {        mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);    }//    @Override    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {        boolean retry = true;        isRunning = false;        while(retry){            try{                mThread.join();                retry = false;            }catch (Exception e){                e.printStackTrace();            }        }    }    private class DrawThread extends Thread{        @Override        public void run() {            Canvas canvas = null;            while(isRunning) {                if (isDrawing) {                    try {                        canvas = getHolder().lockCanvas(null);                        if (mBitmap == null) {                            mBitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);                        }                        Canvas c = new Canvas(mBitmap);                        c.drawColor(0, PorterDuff.Mode.CLEAR);                        canvas.drawColor(0, PorterDuff.Mode.CLEAR);                        mInvoker.execute(c);                        canvas.drawBitmap(mBitmap, 0, 0, null);                    } finally {                        getHolder().unlockCanvasAndPost(canvas);                    }                    isDrawing = false;                }            }        }    }}

最后是把上述整合

package com.example.yale.mydrawbrush;import android.graphics.Paint;import android.graphics.Path;import android.os.SystemClock;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.MotionEvent;import android.view.View;import android.widget.Button;import com.example.yale.mydrawbrush.Brush.CircleBrush;import com.example.yale.mydrawbrush.Brush.DrawCanvas;import com.example.yale.mydrawbrush.Brush.DrawPath;import com.example.yale.mydrawbrush.Brush.IBrush;import com.example.yale.mydrawbrush.Brush.NormalBrush;import butterknife.Bind;import butterknife.ButterKnife;public class MainActivity extends AppCompatActivity {//    private DrawCanvas mCanvas;    private DrawPath mPath;    private Paint mPaint;    private IBrush mBrush;    @Bind(R.id.ac_draw_canvas)    DrawCanvas mCanvas;    @Bind(R.id.ac_draw_draw_operate_undo_btn)    Button btnUndo;    @Bind(R.id.ac_draw_draw_operate_redo_btn)    Button btnRedo;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        ButterKnife.bind(this);        mPaint = new Paint();        mPaint.setColor(0XFFFFFFFF);        mPaint.setStrokeWidth(3);        mCanvas.setOnTouchListener(new DrawTouchListener());        mBrush = new NormalBrush();        btnRedo.setEnabled(false);        btnUndo.setEnabled(false);    }    public void onClick(View view){        switch (view.getId()){            case R.id.ac_draw_color_red_btn:                mPaint = new Paint();                mPaint.setStrokeWidth(3);                mPaint.setColor(0XFFFF0000);                System.out.print("sfsfasfafd!$@#$!@#$!");                break;            case R.id.ac_draw_color_blue_btn:                mPaint = new Paint();                mPaint.setStrokeWidth(3);                mPaint.setColor(0XFF00FF00);                break;            case R.id.ac_draw_color_green_btn:                mPaint = new Paint();                mPaint.setStrokeWidth(3);                mPaint.setColor(0XFF0000FF);                break;            case R.id.ac_draw_draw_operate_undo_btn:                mCanvas.undo();                if(!mCanvas.canUndo()){                    btnUndo.setEnabled(false);                }                btnRedo.setEnabled(true);                break;            case R.id.ac_draw_draw_operate_redo_btn:                mCanvas.redo();                if(!mCanvas.canRedo()){                    btnUndo.setEnabled(false);                }                btnRedo.setEnabled(true);                break;            case R.id.ac_draw_operate_brush_circle_btn:                mBrush = new CircleBrush();                break;            case R.id.ac_draw_operate_brush_normal_btn:                mBrush = new NormalBrush();                break;            default:                break;        }    }    private class DrawTouchListener implements View.OnTouchListener{        @Override        public boolean onTouch(View view, MotionEvent motionEvent) {            if(motionEvent.getAction() == MotionEvent.ACTION_DOWN){                mPath = new DrawPath();                mPath.paint = mPaint;                mPath.path = new Path();                mBrush.down(mPath.path, motionEvent.getX(), motionEvent.getY());            }else if(motionEvent.getAction() == MotionEvent.ACTION_MOVE){                mBrush.move(mPath.path, motionEvent.getX(), motionEvent.getY());            }else if(motionEvent.getAction() == MotionEvent.ACTION_UP){                mBrush.up(mPath.path, motionEvent.getX(), motionEvent.getY());                mCanvas.add(mPath);                mCanvas.isDrawing = true;                btnUndo.setEnabled(true);                btnRedo.setEnabled(false);            }            return true;        }    }}
0 0
原创粉丝点击