首页 > 代码库 > 发布-订阅模式(观察者模式)

发布-订阅模式(观察者模式)

    (一)什么是观察者模式

       发布-订阅,这两个词语是对观察者的最好解释,现实生活中,这样的案例有很多,比如在篮球比赛过程中教练,喊一个暂停,然后球员和裁判都做相关的响应,还有比如OA里面发布的放假通知等等。无论是篮球比赛,还是OA的通知,都存在一个角色,它的作用就是保持对相关问题的关注,在问题发生变化的时候,是Ta把消息通知给相关各方。观察者模式也差不多这样,它抽象一类对象(观察者)专门负责"盯着"目标对象,当目标对象状态有变动的时候,每个观察者就会获得通知并迅速做出响应,观察者模式解决的也是调用通知关系所带来的依赖。

     (二)观察者模式的演变

        下面请看代码。有三个类,A,B,C想接收来自X的消息,简单的说X发生变化,他们也跟着变化。

public class A {
        public int Data;
        public void Update(int data) {
            this.Data =http://www.mamicode.com/ data;
        }
    }

    public class B {
        public int Count;
        public void NotifyCount(int data) {
            this.Count = data;
        }
    }

    public class C {
        public int N;
        public void Set(int data) {
            this.N = data;
        }
    }

    //上面这三个类,类A,B,C是希望获得X通知的类型
    public class X {
        private int data;
        public A InstanceA;
        public B InstanceB;
        public C InstanceC;
        public void SetData(int data) {
            this.data =http://www.mamicode.com/ data;
            InstanceA.Update(data);
            InstanceB.NotifyCount(data);
            InstanceC.Set(data);
        }
    }
在我们调用的时候,应该这么做
A a = new A();
            B b = new B();
            C c = new C();
            X x = new X();
            x.InstanceA = a;
            x.InstanceB = b;
            x.InstanceC = c;
            x.SetData(10);
            Console.WriteLine("x发出消息了");
            Console.WriteLine(a.Data);
            Console.WriteLine(b.Count);
            Console.WriteLine(c.N);
对于上面这种做法,大家应该都会。下面是这个上面例子的类图关系,从这里,我们可以看得X和太多类直接关联了。已经很不符合面向对象的设计原则了。
技术分享

        经过观察,我们发现类A,B,C都有个共同之处,都是有一个类似于更新的方法,如果对他们进行抽象的话呢,就可以让类X仅仅依赖于一个抽象的类型。下面直接看代码

  public interface IUpdatableObject {
        int Data {get;}
        void Update(int newData);
    }

    public class A : IUpdatableObject {

        private int data;
        public int Data { get { return this.data; } }

        public void Update(int newData) {
            this.data =http://www.mamicode.com/ newData;
        }
    }

    public class B : IUpdatableObject {

        private int data;
        public int Data { get { return this.data; } }

        public void Update(int newData) {
            this.data =http://www.mamicode.com/ newData;
        }
    }

    public class C : IUpdatableObject {

        private int data;
        public int Data { get { return this.data; } }

        public void Update(int newData) {
            this.data =http://www.mamicode.com/ newData;
        }
    }

    public class X {
        private IUpdatableObject[] objects = new IUpdatableObject[3];

        //这个是索引器的用法
        public IUpdatableObject this[int index] { set { objects[index] = value; } }

        private int data;
        public void Update(int newData) {
            this.data =http://www.mamicode.com/ newData;
            foreach(IUpdatableObject obj in objects) {
                obj.Update(newData);
            }
        }
    }

//调用代码如下
    X x = new X();
            IUpdatableObject a = new A();
            IUpdatableObject b = new B();
            IUpdatableObject c = new C();
            x[0] = a;
            x[1] = b;
            x[2] = c;
            x.Update(10);
            Console.WriteLine("x发出了消息");
            Console.Write(a.Data);
            Console.Write(b.Data);
            Console.Write(c.Data);

通过上面我们就可以依赖于抽象了,比如当我们要新增加一个订阅者的时候,也不用去类X里面改内部代码,请看类图。

技术分享

   今天先讲到这里,下一篇文章很快就会出,欢迎大家多多指点。

发布-订阅模式(观察者模式)