大话设计模式-观察者模式/事件委托

观察者模式

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


观察者模式的动机

将一个系统分割成一系列相互协作的类有一个很不好的副作用就是需要维护相关对象间的一致性。

我们不希望为了维持一致性而使各类紧密耦合,这样会给维护、扩展和重用都带来不便。

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

当一个抽象模型有两个方面,其中一方面依赖于另一方面,这时用观察者模式可以将这两者封装在独立的对象中使他们各自独立地改变和复用。

观察者模式所做的工作其实就是在解除耦合。让耦合的双方都依赖于抽象,而不是依赖于具体。从而使得各自的变化都不会影响另一边的变化。这时依赖倒转原则的最佳体现。


观察者模式结构演示

通知者抽象类:Subject

一般用一个抽象类或者一个接口实现,把所有观察者的对象的引用保存在一个集合里,每个主题都可以有任何数量的观察者。这里抽象类提供了一个接口可以增加和删除观察者对象。

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 (var o in observers)
            o.Update();
    }
}

观察者抽象类:Observer

为所有具体观察者定义一个接口,在得到统治者的通知时通知自己。一般使用抽象类或者接口实现。接口中定义一个更新方法。

abstract class Observer{
    public abstract void Update();
}

具体通知者类:ConcreteSubject

将有关状态存入具体观察者对象,将变化通知给所有登记过的观察者。

class ConcreteSubject : Subject{
    public string SubjectState { get; set; }
}

具体观察者类:ConcreteObserver

实现观察者抽象类所要求的更新方法,保存一个指向具体通知者的引用,获取其变化。

class ConcreteObserver : Observer{
    private string name;
    private string observerState;
    public ConcreteSubject Subject { get; set; }
    public ConcreteObserver(ConcreteSubject subject,string name){
        Subject = subject;
        this.name = name;
    }
    public override void Update(){
        observerState = Subject.SubjectState;
        Console.WriteLine($"观察者{name}的新状态是{observerState}");
    }
}

测试类:Program

//Main方法
ConcreteSubject s = new ConcreteSubject();
//给通知者添加三个观察者XYZ
s.Attach(new ConcreteObserver(s, "X"));
s.Attach(new ConcreteObserver(s, "Y"));
s.Attach(new ConcreteObserver(s, "Z"));
//通知者更新状态
s.SubjectState = "ABC";
//通知者通知所有订阅的观察者
s.Notify();
//测试结果
观察者X的新状态是ABC
观察者Y的新状态是ABC
观察者Z的新状态是ABC

观察者模式的不足

尽管已经使用了依赖倒转原则,但是抽象通知者依旧是依赖抽象观察者,也就是说如果没有抽象观察者这样的接口,通知的功能就无法实现。此外就是每个具体观察者不一定是更新的方法要调用。


事件委托实现

委托就是一种引用方法的类型,一旦为委托分哦欸了方法,委托将与该方法具有完全相同的行为。委托方法的使用可以像其他任何方法一样,具有参数和返回值。委托可以看作是对函数的抽象,是函数的类,委托的实例将代表一个具体函数。

一个委托可以搭载多个方法,所有方法依次被唤起,可以使委托所搭载的方法并不需要属于同一个类。前提是委托对象所搭载的所有方法必须具有相同的原型和形式,也就是相同的参数列表和返回值类型。

打游戏/看NBA的学生类:Observer

class GameObserver{
    private string name;
    private Subject sub;
    public GameObserver(string name, Subject sub)
    {
        this.name = name;
        this.sub = sub;
    }
    public void CloseGame() => Console.WriteLine($"{sub.SubjectState} {name}关闭游戏,继续写作业");
}
class NBAObserver{
    private string name;
    private Subject sub;
    public NBAObserver(string name, Subject sub)
    {
        this.name = name;
        this.sub = sub;
    }
    public void CloseNBA() => Console.WriteLine($"{sub.SubjectState} {name}关闭NBA视频,继续看书");
}

通知者接口:Subject

interface Subject{
    void Notify();
    string SubjectState { get; set; }
}

事件委托:

delegate void EventHandler();

老师类:

class Teacher : Subject{
    public event EventHandler Update;
    private string action;
    public string SubjectState { get; set; }
    public void Notify() => Update();
}

测试类:Program

//数学老师
Teacher math = new Teacher();
//打游戏的小明同学
GameObserver a = new GameObserver("小明",math);
//看NBA地小杨同学
NBAObserver b = new NBAObserver("小杨", math);
//将二者方法委托到老师的更新上
math.Update += new EventHandler(a.CloseGame);
math.Update += new EventHandler(b.CloseNBA);
//老师回来了
math.SubjectState = "数学老师来教室了!";
//触发通知
math.Notify();
//测试结果
数学老师来教室了! 小明关闭游戏,继续写作业
数学老师来教室了! 小杨关闭NBA视频,继续看书

原文地址:https://www.cnblogs.com/errornull/p/10057852.html

时间: 2024-08-02 17:46:36

大话设计模式-观察者模式/事件委托的相关文章

常用设计模式之观察者模式 + 事件委托

常用设计模式之观察者模式 + 事件委托 作用及UML (摘自<大话设计模式>) Code 1 abstract class Subject{ 2 protected String state; 3 public void setState(String state){this.state = state;} 4 public String getState(){return this.state;} 5 6 private List<Observer> observers = ne

大话设计模式观察者模式

从前,有个放羊娃,每天都去山上放羊,一天,他觉得十分无聊,就想了个捉弄大家寻开心的主意.他向着山下正在种田的农夫们大声喊:"狼来了!狼来了!救命啊!"农夫们听到喊声急忙拿着锄头和镰刀往山上跑,他们边跑喊:"不要怕,孩子,我们来帮你打恶狼!"农夫们气喘吁吁地赶到山上一看,连狼的影子也没有!放羊娃哈哈大笑:"真有意思,你们上当了!"农夫们生气地走了.第二天,放羊娃故伎重演,善良的农夫们又冲上来帮他打狼,可还是没有见到狼的影子.放羊娃笑得直不起腰:&q

观察者设计模式 Vs 事件委托(java)

观察者设计模式 Vs 事件委托 转载请注明原博客地址: http://blog.csdn.net/gdutxiaoxu/article/details/51824769 源码下载地址: http://download.csdn.net/detail/gdutxiaoxu/9567209 本篇博客主要讲解一下几个问题 什么是观察者模式 观察者模式的优缺点 如何看待观察者模式的缺点 事件的委托 什么是观察者模式 简单来说,当有多个观察者想同时观察同一个主题对象的时候,当主题对象的 状态发生变化,观察

C#设计模式 - 观察者模式(使用委托)

1.概念 观察者模式(有时又被称为发布-订阅Subscribe>模式.模型-视图View>模式.源-收听者Listener>模式或从属者模式)是软件设计模式的一种.在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知.这通常透过呼叫各观察者所提供的方法来实现.此种模式通常被用来实现事件处理系统. 2.角色 2.1 抽象主题(Subject):它把所有观察者对象的引用保存到一个聚集里,每个主题都可以有任何数量的观察者.抽象主题提供一个接口,可以增加和

大话设计模式---观察者模式

观察者模式:定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己. 当一个对象的改变需要同时改变其他对象,而且它不知道具体有多少对象有待改变时,应该考虑使用观察者模式. 一个抽象模型有两个方面,其中一方面依赖于另一方面,这时用观察者模式可以将这两者封装在独立的对象中使它们各自独立地改变和复用. 观察者模式所做的工作其实就是在解除耦合.让耦合的双方都依赖于抽象,而不是依赖于具体.从而使得各自的变化都不会影响另

【大话设计模式】设计模式系统学习大合集

转载请注明出处:http://blog.csdn.net/column/details/designpatternbylmb.html 为了方便各位网友学习以及方便自己复习之用,将设计模式的系列内容按照由浅入深的学习顺序总结如下,点击相应的标题即可跳转到对应的文章. 大话设计模式-工厂模式 大话设计模式-单例模式 大话设计模式-原型模式 深复制VS浅复制(MemberwiseClone方法介绍) 大话设计模式-代理模式 大话设计模式-中介者模式 大话设计模式-策略模式 大话设计模式-装饰模式 大

用java语言实现事件委托模式

http://blog.csdn.net/yanshujun/article/details/6494447 用java语言实现事件委托模式 2010-04-27 00:04 2206人阅读 评论(11) 收藏 举报 java语言游戏object设计模式date 事件委托模式是一个比较常用的设计模式,但是Java语言本身没有对其做一定的封装,因此实现起来有一定难度(了解原理后很简单),相比之下.NET就容易了很多. 身为一个Java爱好者,怎么向这样一个小困难低头,但是上网搜索,却没发现相关解决

四、集合与泛型、委托与事件-----《大话设计模式》

一.集合与泛型   数组 集合(ArrayList) 泛型 优点 连续存储.快速从头到尾遍历和修改元素 使用大小可按需动态增加 类型安全:省去拆箱和装箱操作 缺点 创建时必须制定数组变量的大小: 两个元素之间添加元素比较困难 类型不安全,接受所有类型的数据: 导致一直进行拆箱和装箱操作,带来很大的性能消耗   public partial class Form1 : Form { IList arrayAnimal_list = new ArrayList(); //声明并初始化集合 IList

利用事件委托弥补观察者模式不足

前两篇我们自己首先实现了一个观察者模式,我们再利用Java自带的接口和类实现了观察者模式,但其实两种观察者模式存在不足的地方.之前两种观察者模式的观察者(订阅者)都是实现了一个同一个接口,实现了接口中的update方法,但是如果两个观察者风马牛不相及,完全无关呢?或者他们的方法名不一样这个时候该怎么办呢?<大话设计模式>中C#提供了事件委托,但在Java中比没有提供.此时,我们可以利用Java的反射机制来实现事件委托从而来弥补观察者模式的不足. 我们先来看看客户端的测试代码,直观的感受一下和之