惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
Tenable Blog
Last Week in AI
Last Week in AI
P
Proofpoint News Feed
Engineering at Meta
Engineering at Meta
H
Help Net Security
F
Fortinet All Blogs
MyScale Blog
MyScale Blog
宝玉的分享
宝玉的分享
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
博客园 - 司徒正美
量子位
N
Netflix TechBlog - Medium
Apple Machine Learning Research
Apple Machine Learning Research
小众软件
小众软件
Recorded Future
Recorded Future
博客园 - 三生石上(FineUI控件)
Vercel News
Vercel News
aimingoo的专栏
aimingoo的专栏
I
InfoQ
Microsoft Security Blog
Microsoft Security Blog
Scott Helme
Scott Helme
The Last Watchdog
The Last Watchdog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
IT之家
IT之家
AI
AI
WordPress大学
WordPress大学
Security Archives - TechRepublic
Security Archives - TechRepublic
Google Online Security Blog
Google Online Security Blog
U
Unit 42
V2EX - 技术
V2EX - 技术
MongoDB | Blog
MongoDB | Blog
Schneier on Security
Schneier on Security
博客园 - Franky
H
Heimdal Security Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Jina AI
Jina AI
W
WeLiveSecurity
P
Privacy & Cybersecurity Law Blog
Cloudbric
Cloudbric
B
Blog RSS Feed
N
News | PayPal Newsroom
S
Securelist
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
I
Intezer
Hacker News - Newest:
Hacker News - Newest: "LLM"
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
博客园_首页
罗磊的独立博客
H
Hackread – Cybersecurity News, Data Breaches, AI and More
雷峰网
雷峰网

博客园 - Zhongkeruanjian

xxzxz 第三方 Zhongkeruanjian - 博客园 使用状态机工作流 懂得Windows WorkFlow Foundation 使用Windows WorkFlow Foundation Windows Workflow Foundation能带来什么 Windows Workflow Foundation简述 Windows Workflow Foundation简介 我所理解的需求捕获与需求分析 Sql Server 2005恢复脚本 深圳金谷软件招聘DOTNET软件研发工程师(深圳地区) qww 12121 c#中的有用的方法 翻译:在我们使用的NET FRAMEWORK类库中发现设计模式(3) 翻译:在我们使用的NET FRAMEWORK类库中发现设计模式(1) Microsoft Enterprise Library---解读Logging之开篇 Microsoft Enterprise Library---解读Cache之设计与分析
翻译:在我们使用的NET FRAMEWORK类库中发现设计模式(2)
Zhongkeruanjian · 2006-03-18 · via 博客园 - Zhongkeruanjian

观察者模式

Observer :观察者,需要目标对象在发现变化时能获得通知并调用本身某个更新的方法。

Subejct : 目标,即当本身发现变化时能通知每一个观察者。

    好的 OO 设计不但强调封装而且还强调松耦合,换句话说,类要尽可能的封装自己内部的私有细节并且应该将类与类之间的强依赖减小到最少。在大多数应用里,类并不是孤立的,它们之间往往会相互交互和影响。这里有一个很普遍的类与类交互场景:当一个对象( subject )发生改变时,另外一个对象( Observer )要求能收到这个 (subject 改变的 ) 通知。例如:几个窗体控件需要在一个按钮点击后能够改变它们的呈现。一个简单的解决方法就是在 Subject 对象状态改变时直接去调用 Observer 的某一个特定的方法。这种方法将会引入一大把问题:

Subject 需要知道将要调用 Observer 哪一个方法,这种情况将会导致 Subject 与某个特定的 Observer 紧耦合。此外,如果你需要添加另外几个 Observer ,你不得不在 Subject 里添加调用每一个 Observer 方法的代码。如果 Observer 的数量是动态变化的,那么这将更加复杂,你将倒在这种无法维护的混乱之中。

       一个有效的解决方法是使用观察者模式。使用这种方法,你能够将 Subject 与它的那些 Observer 解耦以便能在设计时和运行时轻松的添加和删除任意数量的 Observer Subject 维护着一个 Observer 的列表,每当 Subject 的状态有所改变时,它能够依次通知列表中所有的 Observer 。请看如下的示例代码:

public abstract class CanonicalSubjectBase

{

private ArrayList _observers = new ArrayList();

public void Add(ICanonicalObserver o)

    {

        _observers.Add(o);

}

public void Remove(ICanonicalObserver o)

    {

        _observers.Remove(o);

    }

public void Notify()

    {

        foreach(ICanonicalObserver o in _observers)

        {

            o.Notify();

        }

    }

}

public interface ICanonicalObserver

{

    void Notify();

}

    所有的扮演 Observer 角色的类都实现了 ICanonicalObserver 接口,所有的 Subject 都必须继承自 CanonicalSubjectBase ,如果有一个新的 Observer 想监测 Object ,那么只需要添加此 Observer 的方法而不需要更改 Subject 中的任何一行代码! 而且你会发现 Object 再也不用直接依赖于那些 Observer (因为开始的那个方式是 Object 必须调用每个 Observer 的某个方法,译者注)了,而是仅仅依赖于 ICanonicalObserver 接口。

        尽管四人帮的观察者模式能够解决一些问题,但是这个方式还是有些缺陷,因为 Subejct 必须继承自 CanonicalSubjectBase ,所有的 Observer 必须实现 ICanonicalObserver 接口。(也就是说从一种意义上的紧耦合转移成了另一种意义上的耦合,译者注) , 让我们回头看看那个窗体按钮控件的例子吧,解决的方案就呈现在我们眼前: NET Framework 使用委托和事件来解决这个问题!如果你曾经在 ASP.NET WinForm 中写过程序,那么你可能已经使用过委托和事件,事件就是 Subejct ,而委托就是 Observer ,让我们来看看利用事件来实现的观察者模式的例子:

public delegate void Event1Hander();

public delegate void Event2Handler(int a);

public class Subject

{

public Subject(){}

public Event1Hander Event1;

  public Event2Handler Event2;

public void RaiseEvent1()

  {

     Event1Handler ev = Event1;

     if (ev != null) ev();

   }

public void RaiseEvent2()

  {

     Event2Handler ev = Event2;

     if (ev != null) ev(6);

  }

}

public class Observer1

{   public Observer1(Subject s)

    {

        s.Event1 += new Event1Hander(HandleEvent1);

        s.Event2 += new Event2Handler(HandleEvent2);

}

public void HandleEvent1()

    {

      Console.WriteLine("Observer 1 - Event 1");

}

public void HandleEvent2(int a)

    {

        Console.WriteLine("Observer 1 - Event 2");

    }

}

     窗体按钮控件暴露了一个在按钮点击时能够通知 Observer 的点击事件,任何一个需要响应该事件的 Observer 仅仅只需要向这个事件注册一个委托( new Event1Hander method )便是一个委托,注册一个委托就是 += Event1 事件,译者注)。窗体按钮控件并不依赖于任何一个潜在的 Observer ,每一个 Observer 仅仅只需要知道这个事件的委托签名格式就 OK 了(在这个实例里委托就是 EventHandler ),因为 EventHandler 是一个委托类型而不是一个接口,所以每个 Observer 不需要去实现一个格外的接口,如果一个 Observer 已经有了一个符合委托签名格式的方法,那么它仅仅只需要把这个方法注册到 Subject 的事件中去。通过使用委托和事件,观察者模式能将 Subject Observer 解耦(也就是 Subject 不需要显式的去调用 Observer 的某一个方法)!