C#設計模式——命令模式(Command Pattern)


一、概述
通常來說,“行為請求者”與“行為實現者”是緊耦合的。但在某些場合,比如要對行為進行“記錄、撤銷/重做、事務”等處理,這種無法抵御變化的緊耦合是不合適的。在這些情況下,將“行為請求者”與“行為實現者”解耦,實現二者之間的松耦合就至關重要。命令模式是解決這類問題的一個比較好的方法。
二、命令模式
命令模式將一個請求封裝為一個對象,從而使你可用不同的請求對客戶進行參數化;對請求排隊或記錄請求日志,以及支持可撤銷的操作。
命令模式的結構圖如下

Command定義了命令的接口
ConcreteCommand實現Command接口,定義了具體的命令
Client用於創建具體的命令並設定接收者
Invoker要求Command執行相應的請求
Receiver實施與執行一個請求,任何一個類都可能作為Receiver。
三、示例
假定要實現一個繪圖系統,要求支持撤銷功能,下面就用命令模式來實現這一需求。
首先定義一個抽象的命令接口

 public interface IGraphCommand
 {
     void Draw();
     void Undo();
 }

接着實現具體的繪圖命令

public class Line : IGraphCommand
    {
        private Point startPoint;
        private Point endPoint;
        public Line(Point start, Point end)
        {
            startPoint = start;
            endPoint = end;
        }

        public void Draw()
        {
            Console.WriteLine("Draw Line:{0} To {1}", startPoint.ToString(), endPoint.ToString());
        }

        public void Undo()
        {
            Console.WriteLine("Erase Line:{0} To {1}", startPoint.ToString(), endPoint.ToString());
        }
    }

    public class Rectangle : IGraphCommand
    {
        private Point topLeftPoint;
        private Point bottomRightPoint;
        public Rectangle(Point topLeft, Point bottomRight)
        {
            topLeftPoint = topLeft;
            bottomRightPoint = bottomRight;
        }

        public void Draw()
        {
            Console.WriteLine("Draw Rectangle: Top Left Point {0},  Bottom Right Point {1}", topLeftPoint.ToString(), bottomRightPoint.ToString());
        }

        public void Undo()
        {
            Console.WriteLine("Erase Rectangle: Top Left Point {0},  Bottom Right Point {1}", topLeftPoint.ToString(), bottomRightPoint.ToString());
        }
    }

    public class Circle : IGraphCommand
    {
        private Point centerPoint;
        private int radius;
        public Circle(Point center, int radius)
        {
            centerPoint = center;
            this.radius = radius;
        }

        public void Draw()
        {
            Console.WriteLine("Draw Circle: Center Point {0},  Radius {1}", centerPoint.ToString(), radius.ToString());
        }

        publi cvoid Undo()
        {
            Console.WriteLine("Erase Circle: Center Point {0},  Radius {1}", centerPoint.ToString(), radius.ToString());
        }
    }

然后再定義繪圖類作為命令接收者

public class Graphics
    {
        Stack<IGraphCommand> commands =new Stack<IGraphCommand>();

public void Draw(IGraphCommand command)
        {
            command.Draw();
            commands.Push(command);
        }

public void Undo()
        {
            IGraphCommand command = commands.Pop();
            command.Undo();
        }
    }

最后看一下如何調用

static void Main(string[] args)
    {
        Line line =new Line(new Point(10, 10), new Point(100, 10));
        Rectangle rectangle =new Rectangle(new Point(20, 20), new Point(50, 30));
        Circle circle =new Circle(new Point(500, 500), 200);

        Graphics graphics =new Graphics();
        graphics.Draw(line);
        graphics.Draw(rectangle);
        graphics.Undo();
        graphics.Draw(circle);

        Console.ReadLine();
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM