您的位置:首页 > 其它

大话设计模式-第14章 老板回来,我不知道--观察模式

2016-06-15 14:15 513 查看
第14章
老板回来,我不知道--观察模式

14.1 老板回来?我不知道!

14.2 双向耦合代码

class Secretary

{

    //同事列表

    private IList<StockObserver> observers = new List<StockObserver>();

    private string action;

    //增加

    public void Attach(StockObserver observer)

    {

        observer.Add(observer);

    }

    //通知

    public void Notify()

    {

        foreach(StockObserver o in observers)

        {

            o.Update();

        }

    }

    //前台状态

    public string SecretaryAction

    {

        get{ return action; }

        set{ action = value;}

    }

}

看股票同事类

class StockObserver

{

    private string name;

    private Secretary sub;

    public StockObserver(String name,Secretary sub)

    {

        this.name = name;

        this.sub = sub;

    }

    public void Update()

    {

        Console.WriteLine(“{0} {1} 关闭股票行情,继续工作!”,sub.SecretaryAction,name);

    }

}

客户端程序如下

static void Main(string[] args)

{

    //前台小姐

    Secretary tongzizhe = new Secretary();

    //看股票的同事

    StockObserver tongshi1 = new StockObserver(“未关严”,tongzizhe);

    StockObserver tongshi2 = new StockObserver(“善观察”,tongzizhe);

    //前台记下了两位同事

    tongzizhe.Attach(tongshi1);

    tongzizhe.Attach(tongshi2);

    //发现老板回来

    tongzizhe.SecretaryAction = “老板回来了!”;

    //通知两个同事

    tongzizhe.Notify();

    Console.Read();

}

观察上面的代码可以发现,前台类和同事之间相互耦合。

14.3 解耦实践一

//抽象的观察者

abstract class Observer

{

    protect string name;

    protected Secretary sub;

    public Observer(string name,Secretary sub)

    {

        this.name = name;

        this.sub = sub;

    }

    public abstract void Update();

}

//看股票的同事

class StockObserver : Observer

{

    public StockObserver(string name, Secretary sub) : base(name,sub)

    {

    }

    public override void Update()

    {

        Console.WriteLine(“{0} {1} 关闭股票行情,继续工作!”,sub.SecretaryAction,name);

    }

}

//看NBA的同事

class NBAObserver : Observer

{

    public NBAObserver(string name,Secretary sub) : base(name,sub)

    {

    }

    public override void Update()

    {

        Console.WriteLine(“{0} {1} 关闭NBA直播,继续工作!”,sub.SecretaryAction,name);

    }

}

//前台秘书类

class Secretary

{

    //同事列表

    private IList<Observer> observers = new List<Observer>();

    private string action;

    //增加,针对抽象结成,减少了与具体类的耦合

    public void Attach(Observer observer)

    {

        observer.Add(observer);

    }

    //减少,针对抽象结成,减少了与具体类的耦合

    public void Detach(Observer observer)

    {

        observers.Remove(observer);

    }

    //通知

    public void Notify()

    {

        foreach(observer o in observers)

        {

            o.Update();

        }

    }

    //前台状态

    public string SecretaryAction

    {

        get{ return action; }

        set{ action = value;}

    }

}

14.4 解耦实践二

//通知者接口

interface Subject

{

    void Attach(Observer observer);

    void Detach(Observer observer);

    void Notify();

    string SubjectState

    {

        get;

        set;

    }

}

//老板类

class Boss : Subject

{

    //同事列表

    private IList<Observer> observers = new List<Observer>();

    private string action;

    //增加

    public void Attach(Observer observer)

    {

        observer.Add(observer);

    }

    //减少

    public void Detach(Observer observer)

    {

        observers.Remove(observer);

    }

    //通知

    public void Notify()

    {

        foreach(Observer o in observers)

        {

            o.Update();

        }

    }

    //老板状态

    public string SubjectState

    {

        get { return action; }

        set { action = value;}

    }

}

//秘书类类似

//抽象观察者

abstract class Observer

{

    protected string name;

    protected Subject sub;

    public Observer(string name, Subject sub)

    {

        this.name = name;

        this.sub = sub;

    }

    public abstract void Update();

}

//看股票的同事

class StockObserver : Observer

{

    // 原来是“前台”,现在改成“抽象通知者”

    public StockObserver(string name,Subject sub) : base(name,sub)

    {

    }

    public override void Update()

    {

        Console.EriteLine(“{0} {1} 关闭股票行情,继续工作”,sub.SubjiectState,name);

    }

}

客户端代码

Boss huhansan = new Boss();

//看股票的同事

StockObserver tongshi1 = new StockObserver(“未关严”,huhansan);

//看NBA的同事

NBAObserver tongshi2 = new NBAObserver(“善观察”,huhansan);

huhansan.Attach(tongshi1);

huhansan.Attach(tongshi2);

//未关严实际上并没有被通知到

huhansan.Detach(tongshi1);

//老板回来

huhansan.SubjectState = “我胡汉三回来了!”;

//发出通知

huhansan.Notify();



14.5 观察者模式

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



Subject类,可翻译为主题或抽象通知者,被观察者:

abstract class Subject

{

    private IList<observer> observers = new List<Observer>();

    //增加观察者

    public void Attach(Observer observer)

    {

        observers.Add(observer);

    }

    //移除观察者

    public void Detch(Observer observer)

    {

        observers.Remove(observer);

    }

    //通知

    public void Notify()

    {

        foreach(Observer o in observers)

        {

            o.Update();

        }

    }

}

Observer类,抽象观察者

abstract class Observer

{

    public abstract void Update();

}

ConcreteSubject类:具体主题类或具体通知者

class ConcreteSubject : Subject

{

    private string subjectState;

    //具体被观察者状态

    public string SubjectState

    {

        get { return subjectState; }

        set { subjectState = value;}

    }

}

    ConcreteObserver类,具体观察者,实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。具体观察者角色可以保存一个指向具体主题对象(被观察者)的引用(以便获得其最新状态)。

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 = “AEC”;

    s.Notify();

    Console.Read();

}

14.6 观察者模式特点

    将一个系统分割成一系列相互协作的类有一个很不好的副作用,那就是需要维护相关对象间的一致性。我们不希望为了维护一致性而使各类紧密耦合,这样会给维护、扩展和重用都带来不便。

    当一个对象改变需要同时更改其他对象时,而且他不知道具体多少对象有待改变时,应该考虑使用观察者模式。

    观察者模式所做的工作其实就是接触耦合。让耦合的双方都依赖于抽象,而不是依赖于具体。从而使的各自的变化都不会影响到另一边的变化。

14.7 观察者的不足

    观察者模式中,观察者类还是依赖于抽象的Update接口,被观察者也是通过操作此接口达到目的。如果某些观察者是系统已经实现好的类怎么办。

    如果观察者与被观察者之间互不相识怎么办。

14.8 事件委托实现

    “看股票观察者“类和”看NBA观察者“类,去掉了父类”抽象观察者“,所以补上一些代码,并将”更新“方法更改为各自适合的方法名。

//看股票的同事

class StockObserver

{

    private string name;

    private Subject sub;

    public StockObserver(string name,Subject sub)

    {

        this.name = name;

        this.sub = sub;

    }

    //关闭股票行情

    public void CloseStockMarket()

    {

        Console.WriteLine(“观察者{0}的新状态是{1}关闭股票行情、继续工作”, name, sub.SubjectState);

    }

}

//看NBA的同事

class NBAObserver

{

    private string name;

    private Subject sub;

    public NBAObserver(string name,Subject sub)

    {

        this.name = name;

        this.sub = sub;

    }

    //关闭NBA直播

    public void CloseNBADirectSeeding()

    {

        Console.WriteLine(“观察者{0}的新状态是{1}关闭NBA直播”, name, sub.SubjectState);

    }

}

现实中就是这样的,方法名就不一定相同

//通知者接口

interface Subject

{

    void Notify();

    string SubjectState

    {

        get;

        set;

    }

}

声明一个委托,名称叫“EventHandler”,无参数,无返回值。

delegate void EventHandler();

“老板“类和”前台秘书“类

class Boss : Subject

{

    //声明一件事Update,类型为委托EventHandler

    public event EventHandler Update;

    private string action;

    public void Notify()

    {

        Update();

    }

    public string SubjectState

    {

        get { return action; }

        set { action = value;}

    }

}

class Secretary : Subject

{

    //老板类类似,略高

}

//客户端代码

//老板胡汉三

Boss huhansan = new Boss();

//看股票的同事

StockObserver tongshi1 = new StockObserver(“未关严”,huhansan);

//看NBA的同事

NBAObserver tongshi2 = new NBAObserver(“善观察”,huhansan);

huhansan.Update += new EventHandle(tongshi1.CloseStockMarket);

huhansan.Update += new EventHandler(tongshi2.CloseNBADirectSeeding);

//老板回来

huhansan.SubjectState = “我胡汉三回来了”;

//发出通知

huhansan.Notfy();

14.9 事件委托说明

    Windows的技术,委托相当于函数的抽象,但是其搭载的函数,必须具有相同的参数和返回值。还是没有OC的动态运行时技术强大。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: