zoukankan      html  css  js  c++  java
  • 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();
        }
  • 相关阅读:
    从零开始入门 K8s | 应用编排与管理
    209. Minimum Size Subarray Sum
    208. Implement Trie (Prefix Tree)
    207. Course Schedule
    203. Remove Linked List Elements
    183. Customers Who Never Order
    182. Duplicate Emails
    181. Employees Earning More Than Their Managers
    1261. Find Elements in a Contaminated Binary Tree
    1260. Shift 2D Grid
  • 原文地址:https://www.cnblogs.com/zhiLong/p/12057609.html
Copyright © 2011-2022 走看看