敏捷软件开发 13~16

COMMAND 模式 & Active Object 模式

先上图:

命令模式有以下的优点:

1. 能够比较容易地设计一个命令队列 
2. 能够在一些情况下将命令记录日志 
3. 允许接收请求的一方决定是否要否决请求 
4. 容易实现对请求的撤销和重做 
5. 加入新的命令类不需要改变其他的类 
6. 把请求一个操作的对象与知道怎么执行一个操作的对象分割开

实例:(来自大话设计模式)

using System;
using System.Collections.Generic;
using System.Text;

namespace 命令模式
{
    class Program
    {
        static void Main(string[] args)
        {
            Receiver r = new Receiver();
            Command c = new ConcreteCommand(r);
            Invoker i = new Invoker();

            // Set and execute command 
            i.SetCommand(c);
            i.ExecuteCommand();

            Console.Read();

        }
    }

    /// <summary>
    /// Command类,用来声明执行操作的接口
    /// </summary>
    abstract class Command
    {
        protected Receiver receiver;

        public Command(Receiver receiver)
        {
            this.receiver = receiver;
        }

        abstract public void Execute();
    }

    /// <summary>
    /// ConcreteCommand 具体命令类,将一个接收者对象绑定于一个动作,调用接收者相应该的操作以实现Excecute
    /// </summary>
    class ConcreteCommand : Command
    {
        public ConcreteCommand(Receiver receiver)
            :
          base(receiver) { }

        public override void Execute()
        {
            receiver.Action();
        }
    }
    /// <summary>
    /// Receiver类,知道如何实施与执行一个与请求相关的操作,任何类都可能作为一个接收者
    /// </summary>
    class Receiver
    {
        public void Action()
        {
            Console.WriteLine("执行请求!");
        }
    }
    /// <summary>
    /// Invoker 类,要求该命令执行这个请求
    /// </summary>
    class Invoker
    {
        private Command command;

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

        public void ExecuteCommand()
        {
            command.Execute();
        }
    }


}

主动对象模式(Active Object pattern) 用作者的话来说这是他最喜欢使用COMMAND模式的地方之一。这是实现多线程控制的一项古老的技术。这种类型的线程称为run-to-completion任务(RTC),因为每个Command实例在下一个Command实例可以运行之前就运行完成了,并不会阻塞。

上代码:

using System;
using System.Collections.Generic;
using System.Text;

namespace ActiveObject
{
    public interface ICommand
    {
        void Execute();
    }
    
     public class ActiveObjectEngine
    {
        ArrayList itsCommands = new ArrayList();

        public void AddCommand(ICommand aCommand)
        {
            itsCommands.Add(aCommand);
        }

        public void Run()
        {
            while (itsCommands.Count > 0)
            {
                ICommand c = (ICommand)itsCommands[0];
                itsCommands.RemoveAt(0);
                c.Execute();
            }
        }
    }


 public class SleepCommand : ICommand
    {
        private ICommand wakeupCommand = null;
        private ActiveObjectEngine engine = null;
        private long SleepTime = 0;
        private DateTime startTime;
        private bool started = false;

        public SleepCommand(long milliSeconds, ActiveObjectEngine e,
            ICommand wakeupCommand)
        {
            this.SleepTime = milliSeconds;
            this.engine = e;
            this.wakeupCommand = wakeupCommand;
        }

        public void Execute()
        {
            DateTime currentTime = DateTime.Now;
            if (!started)
            {
                started = true;
                this.startTime = currentTime;
                this.engine.AddCommand(this);
            }
            else
            {
                TimeSpan elapsedTime = currentTime - startTime;
                if (elapsedTime.TotalMilliseconds < SleepTime)
                {
                    this.engine.AddCommand(this);
                }
                else
                {
                    this.engine.AddCommand(this.wakeupCommand);
                }
            }
        }
    }

  public class DelayedTyper : ICommand
    {
        private long itsDelay;
        private char itsChar;
        private static bool stop = false;
        private static ActiveObjectEngine engin =
            new ActiveObjectEngine();

        private class StopCommand : ICommand
        {
            public void Execute()
            {
                DelayedTyper.stop = true;
            }
        }

        public static void Main(string[] args)
        {
            engin.AddCommand(new DelayedTyper(100, 'A'));
            engin.AddCommand(new DelayedTyper(300, 'B'));
            engin.AddCommand(new DelayedTyper(500, 'C'));
            engin.AddCommand(new DelayedTyper(700, 'D'));

            ICommand stopCommand = new StopCommand();
            engin.AddCommand(new SleepCommand(2000, engin, stopCommand));
            engin.Run();

            Console.ReadLine();
        }

        public DelayedTyper(long delay, char c)
        {
            this.itsDelay = delay;
            this.itsChar = c;
        }

        public void Execute()
        {
            Console.Write(itsChar);
            if (!stop)
            {
                DelayAndRepeat();
            }
        }

        private void DelayAndRepeat()
        {
            engin.AddCommand(new SleepCommand(itsDelay, engin, this));
        }
    }

}
    

 TEMPLATE METHOD模式和STRATEGY模式

模板方法模式:定义一个操作中的算法骨架,将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

作者指出,继承是一种非常强的关系,派生类不可避免地要和它们的基类绑定在一起。由于继承了BubbleSorter,就注定要把IntBubbleSorter永远地和BubbleSorter绑定在一起。因此STRATEGY模式(策略模式)提供了另一种可选方案。

策略模式:一种定义一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合。

 如图:

具体的策略类通过继承Strategy类,提供给Context不同的算法实现。

FACADE模式,MEDIATOR模式

FACADE模式(外观模式):由外观类去保存各个子系统的引用,实现由一个统一的外观类去包装多个子系统类,然而客户端只需要引用这个外观类,然后由外观类来调用各个子系统中的方法。

MEDIATOR模式(中介者模式):定义了一个中介对象来封装系列对象之间的交互。中介者使各个对象不需要显式地相互引用,从而使其耦合性降低,而且可以独立地改变它们之间的交互。中介者模式一般应用于一组定义良好的对象之间需要进行通信的场合以及想定制一个分布在多个类中的行为,而又不想生成太多的子类的情形下。

SINGLETON模式和MONOSTATE模式 

SINGLETON模式(单例模式)确保一个类只有一个实例,并提供一个全局访问点

 

/// <summary>
    /// 单例模式的实现
    /// </summary>
    public class Singleton
    {
        // 定义一个静态变量来保存类的实例
        private static Singleton uniqueInstance;

        // 定义一个标识确保线程同步
        private static readonly object locker = new object();

        // 定义私有构造函数,使外界不能创建该类实例
        private Singleton()
        {
        }

        /// <summary>
        /// 定义公有方法提供一个全局访问点,同时你也可以定义公有属性来提供全局访问点
        /// </summary>
        /// <returns></returns>
        public static Singleton GetInstance()
        {
            // 当第一个线程运行到这里时,此时会对locker对象 "加锁",
            // 当第二个线程运行该方法时,首先检测到locker对象为"加锁"状态,该线程就会挂起等待第一个线程解锁
            // lock语句运行完之后(即线程运行完之后)会对该对象"解锁"
            // 双重锁定只需要一句判断就可以了
            if (uniqueInstance == null)
            {
                lock (locker)
                {
                    // 如果类的实例不存在则创建,否则直接返回
                    if (uniqueInstance == null)
                    {
                        uniqueInstance = new Singleton();
                    }
                }
            }
            return uniqueInstance;
        }
    }

 MONOSTATE模式(单态模式):与单例模式相比,单例关注结构,单态关注行为。单例强制结构上的单一性,它防止创建出多个对象实例。相反,单态模式则强制行为上的单一性。

实例:

public class MonoState {
    private static String x;
    
    public MonoState(){}
    
    public String GetX() {
                            return x;
    }

    public void SetX(String x) {
           MonoState.x = x;
    }
}

 

 

参考:《敏捷软件开发:原则、模式与实践》

           《大话设计模式》

            https://www.cnblogs.com/zhili/

posted @ 2019-03-30 10:29  秋官  阅读(183)  评论(0编辑  收藏  举报