首页 > 代码库 > 设计模式之观察者模式

设计模式之观察者模式

观察者模式

技术分享

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

 1. Subject是对主题的抽象,但具体维护通知对象是在子类ConcreteSubject的实现中,ConcreteSubject调用它的notify来遍历通知对象。

 2. ConcreteSubject是具体的主题,也是我们关心的对象,当它的subjectState修改的时候,同时调用父类的notify.实现通知

3. 当一个对象需要通知或改变其它对象,而它又不能假定其它对象是谁,也就是说 ,不希望这些对象是紧耦合的,我们就可能考虑它

 

观察者模在通信的具体实现中,有两个版本。

1) 拉模式:目标角色在发生变化后,仅仅告诉观察者角色“我变化了”;观察者角色如果想要知道具体的变化细节,则就要自己从目标角色的接口中得到。拉模式是想要就主动表白获取。这里存在依赖,观察者要依赖具体的主题 。

2) 推模式:通知你发生变化的同时,通过一个参数将变化的细节传递到观察者角色中去。推模式是管你要不要,先给你啦。推模型可能会使得观察者对象难以复用,因为观察者的update()方法是按需要定义的参数,可能无法兼顾没有考虑到的使用情况

而拉模型就不会造成这样的情况,因为拉模型下,update()方法的参数是主题对象本身,这基本上是主题对象能传递的最大数据集合了,基本上可以适应各种情况的需要

 

 以下是拉模式 代码如下: 实现的逻辑:当门打开时,主卧和客厅的灯亮起,电视打开。

 

/// <summary>
    /// 抽象主题 
    /// </summary>
    public abstract class Subject
    {
        private List<Observer> observers = new List<Observer>();

        public void Add(Observer observer)
        {
            observers.Add(observer);
        }
        public void Remove(Observer observer)
        {
            observers.Remove(observer);
        }

        /// <summary>
        /// 通知所有观察者
        /// </summary>
        public void Notify()
        {
            observers.ForEach(o => o.Action(this));
        }
    }

    public class Door :Subject
    {
        public string DoorState { get; set; }
        public void Open()
        {
            this.DoorState = "开启";

            Console.WriteLine(string.Format("门开起"));
            base.Notify();
        }
    }

    public abstract class Observer
    {
        public abstract void Action(Subject subject);
    }

    public class Light : Observer
    {
        private string name;

        public Light(string name)
        {
            this.name = name;
        }
        public override void Action(Subject subject)
        {
            var door = (Door)subject;
            
            Console.WriteLine(string.Format("门{0},{1}灯 亮起",door.DoorState, this.name));
        }
    }

    public class TV : Observer
    {
        public override void Action(Subject subject)
        {
            Console.WriteLine(string.Format("TV 打开"));
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Console.OutputEncoding = Encoding.UTF8;

            Observer masterRoom = new Light("主卧室");
            Observer LivingRoom = new Light("客厅");
            Observer tv = new TV();

            Door door = new Door();
            door.Add(masterRoom);
            door.Add(LivingRoom);
            door.Add(tv);

            door.Open();

            Console.ReadKey();
        }
    }

 

C# 提供了事件的机制,同样可以实现观察者模式,与上面代码稍有不同:

//继承自EventArgs
    //用作保存状态,还可以扩展其他的功能
    public class StateChangeEventArgs : EventArgs
    {
        public string State { get; set; }
        public StateChangeEventArgs(string state)
        {
            this.State = state;
        }
    }

    //定义一个委托 
    public delegate void StateChangeEventHandler(object sender, StateChangeEventArgs e);

    public class Door
    {
        public event StateChangeEventHandler StateChange;

        public string DoorState { get; set; }
        public void Open()
        {
            this.DoorState = "开启";

            Console.WriteLine(string.Format("门开起"));
            StateChangeEventArgs e = new StateChangeEventArgs(this.DoorState);
            StateChange(this, e);
        }
    }

    public abstract class Observer
    {
        public abstract void Action(object sender, StateChangeEventArgs e);
    }

    public class Light : Observer
    {
        private string name;

        public Light(string name)
        {
            this.name = name;
        }
        public override void Action(object sender, StateChangeEventArgs e)
        {

            Console.WriteLine(string.Format("门{0},{1}灯 亮起", e.State, this.name));
        }
    }

    public class TV : Observer
    {
        public override void Action(object sender, StateChangeEventArgs e)
        {
            Console.WriteLine(string.Format("TV 打开"));
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Console.OutputEncoding = Encoding.UTF8;

            Observer masterRoom = new Light("主卧室");
            Observer livingRoom = new Light("客厅");
            Observer tv = new TV();

            Door door = new Door();

            door.StateChange += masterRoom.Action;
            door.StateChange += livingRoom.Action;
            door.StateChange += tv.Action;

            door.Open();

            Console.ReadKey();
        }
    }

 

设计模式之观察者模式