• 十、行为型模式之观察者、命令、状态-----《大话设计模式》


    一、观察者模式

        定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

        观察者模式的关键对象是主题Subject和观察者Observer,一个Subject可以有任意数目的依赖它的Observer,一旦Subject的状态发生了改变,所有的Observer都可以得到通知。

    适用:当一个对象的改变需要同时改变其他对象的时候,而且它不知道具体有多少对象有待改变时,应该考虑使用观察者模式;当一个抽象模型有两个方面,其中一方面依赖于另一方面,这时用观察者模式可以将这 封装在独立的对象中使它们各自独立地改变和复用。

    PS:将观察者模式和事件委托相结合可以弥补其解耦不充分的缺陷。一个委托可以搭载多个方法。

    image

    abstract class Subject
        {
            private IList<Observer> observers = new List<Observer>();
    
            //增加观察者
            public void Attach(Observer observer)
            {
                observers.Add(observer);
            }
            //移除观察者
            public void Detach(Observer observer)
            {
                observers.Remove(observer);
            }
            //通知
            public void Notify()
            {
                foreach (Observer o in observers)
                {
                    o.Update();
                }
            }
        }
    
        //具体通知者
        class ConcreteSubject : Subject
        {
            private string subjectState;
    
            //具体通知者状态
            public string SubjectState
            {
                get { return subjectState; }
                set { subjectState = value; }
            }
        }
        //抽象观察者 
        abstract class Observer
        {
            public abstract void Update();
        }
    
        //具体观察者
         class ConcreteObserver : Observer
        {
            private string name;
            private string observerState;
            private ConcreteSubject subject;
    
            public ConcreteObserver(
              ConcreteSubject subject, string name)
            {
                this.subject = subject;
                this.name = name;
            }
            //更新
            public override void Update()
            {
                observerState = subject.SubjectState;
                Console.WriteLine("观察者{0}的新状态是{1}",
                  name, observerState);
            }
    
            public ConcreteSubject Subject
            {
                get { return subject; }
                set { subject = value; }
            }
        }
            static void Main(string[] args)
            {
                ConcreteSubject s = new ConcreteSubject();
    
                s.Attach(new ConcreteObserver(s, "X"));
                s.Attach(new ConcreteObserver(s, "Y"));
                s.Attach(new ConcreteObserver(s, "Z"));
    
                s.SubjectState = "ABC";
                s.Notify();
    
                Console.Read();
    
            }

    二、命令模式

        将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。

    适用:在不同的时刻指定、排列和执行请求;支持取消/重做的操作;记录整个操作的日志;支持事务。

    优点:1.能较容易地设计一个命令队列;
             2.在需要的情况下,可以较容易地将命令记入日志;
             3.允许接收请求的一方决定是否要否决请求;
             4.可以容易地实现对请求的撤销和重做;
             5.由于加进新的具体命令类不影响其他的类,因此增加新的具体命令类很容易;
             6.把请求一个操作的对象与知道怎么执行一个操作的对象分割开。

    image

    //抽象执行操作类
        abstract class Command
        {
            protected Receiver receiver;
    
            public Command(Receiver receiver)
            {
                this.receiver = receiver;
            }
    
            abstract public void Execute();
        }
    
       //具体操作
        class ConcreteCommand : Command
        {
            public ConcreteCommand(Receiver receiver) : base(receiver)
            { 
            }
            public override void Execute()
            {
                receiver.Action();
            }
        }
    //执行操作
        class Receiver
        {
            public void Action()
            {
                Console.WriteLine("执行请求!");
            }
        }
    
        //请求
        class Invoker
        {
            private Command command;
    
            public void SetCommand(Command command)
            {
                this.command = command;
            }
    
            public void ExecuteCommand()
            {
                command.Execute();
            }
        }
    //创建一个具体命令对象并设定它的接收者
            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();
    
            }

    三、状态模式

        当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。

        决定状态转移的逻辑不在单块的if或switch中,而是分布在各个状态子类之间,所以通过定义新的子类可以很容易地增加新的状态和转换。

    image

    class Context
        {
            private State state;
    
            public Context(State state)
            {
                this.state = state;
            }
    
            public State State
            {
                get
                {
                    return state;
                }
                set
                {
                    state = value;
                    Console.WriteLine("当前状态:" + state.GetType().Name);
                }
            }
    
            public void Request()
            {
                state.Handle(this);
            }
        }
    abstract class State
        {
            public abstract void Handle(Context context);
        }
    
        class ConcreteStateA : State
        {
            public override void Handle(Context context)
            {
                context.State = new ConcreteStateB();
            }
        }
    
        class ConcreteStateB : State
        {
            public override void Handle(Context context)
            {
                context.State = new ConcreteStateA();
            }
        }
    static void Main(string[] args)
            {
                Context c = new Context(new ConcreteStateA());
    
                c.Request();
                c.Request();
                c.Request();
                c.Request();
    
                Console.Read();
            }
  • 相关阅读:
    acm的STL容器之vector篇
    服务器远程管理方法及centos该装那个
    VB获取对象成员
    获取搜索引擎关键字建议
    IntelliJ IDEA乱码 问题
    排序算法思想
    ubuntu16 开机启动plank
    fail-fast出识
    html 标签过滤、转译、反转译
    (a ==1 && a== 2 && a==3) 有可能是 true 吗?
  • 原文地址:https://www.cnblogs.com/shanymen/p/4833562.html
Copyright © 2020-2023  润新知