• 观察者模式(Observer Pattern)


    模式定义

    观察者模式(Observer Pattern):定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。

    UML类图

    • 观察目标(Subject) 也称被观察的对象,有观察者类型集合字段,并提供订阅Attach(Observer observer)和取消订阅方法Detach(Observer observer),以及通知观察者方法Notify()
    • 具体观察目标(ConcreteSubject) 目标类的子类,通常它包含有经常发生改变的数据,当它的状态发生改变时,调用通知方法。
    • 观察者(Observer) 定义对观察目标的改变做出操作Update()抽象方法
    • 具体观察者(ConcreteObserver) 实现抽象观察者角色接口,(如果需要目标类更多信息,则需要依赖具体目标类)

    代码结构

    	public class ObserverApp
    	{
    		public void Run()
    		{
    			ConcreteSubject s = new ConcreteSubject();
    
    			s.Attach(new ConcreteObserver() { Subject = s, Name = "X" });
    			s.Attach(new ConcreteObserver() { Subject = s, Name = "Y" });
    			s.Attach(new ConcreteObserver() { Subject = s, Name = "Z" });
    
    			s.SubjectState = "ABC";
    			s.Notify();
    		}
    	}
    
    	abstract class Subject
    	{
    
    		private List<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(Observer o in _observers)
    			{
    				o.Update();
    			}
    		}
    	}
    
    	class ConcreteSubject : Subject
    	{
    		public string SubjectState { get; set; }
    	}
    
    	abstract class Observer
    	{
    		public abstract void Update();
    	}
    
    	class ConcreteObserver : Observer
    	{
    		public string Name { get; set; }
    		public ConcreteSubject Subject { get; set; }
    
    		public override void Update()
    		{
    			string state = this.Subject.SubjectState;
    			Console.WriteLine("Observer {0}'s new state is {1}",this.Name,state);
    		}
    	}
    

    情景案例

    现在大家最关心的应该是回家过年的火车票,相信大家电脑上也安装了些刷票的软件吧!这样才能安心工作,等有票了自动通知。

    public class ObserverApp
    	{
    		public void Run()
    		{
    			Ticket360 s = new Ticket360();
    
    			s.Attach(new ConcreteCustomer() { Subject = s, Name = "小王" });
    			s.Attach(new ConcreteCustomer() { Subject = s, Name = "小赵" });
    			s.Attach(new ConcreteCustomer() { Subject = s, Name = "小孙" });
    
    			s.TicketState = "有坐票";
    			s.Notify();
    		}
    	}
    
    	/// <summary>
    	/// 火车票
    	/// </summary>
    	abstract class Ticket
    	{
    
    		private List<Customer> _observers = new List<Customer>();
    
    		public void Attach(Customer observer)
    		{
    			_observers.Add(observer);
    		}
    
    		public void Detach(Customer observer)
    		{
    			_observers.Remove(observer);
    		}
    
    		public void Notify()
    		{
    			foreach (Customer o in _observers)
    			{
    				o.Notify();
    			}
    		}
    	}
    
    	class Ticket360 : Ticket
    	{
    		public string TicketState { get; set; }
    	}
    
    	abstract class Customer
    	{
    		public abstract void Notify();
    	}
    
    	class ConcreteCustomer : Customer
    	{
    		public string Name { get; set; }
    		public Ticket360 Subject { get; set; }
    
    		public override void Notify()
    		{
    			string state = this.Subject.TicketState;
    			Console.WriteLine("{0}顾客关注的火车票现在状态为 {1}", this.Name, state);
    		}
    	}
    

    C#中的优化

    在C#中其实可以通过delegateEvent,可参数传递函数,更方便的实现观察者模式。

  • 相关阅读:
    用Photoshop设计网站的70个教程
    反射引发的错误“reflection Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.”
    机械键盘理解的几个误区和保养方法
    Asp.Net MVC中不指定View Name时如何返回ActionResult的
    [通告]Nuget服务宕机,出现 503 Server Unavailable 错误无法编译及解决方法
    MVC标签链接切换帮助类: TabLink
    [Centos 6.2] centos 6.2(64位)网络配置
    Linux(Ubuntu)设置环境变量(转载)
    COPYONWRITE 原理
    [Linux 技巧] linux screen 命令详解
  • 原文地址:https://www.cnblogs.com/LoveTomato/p/8447099.html
Copyright © 2020-2023  润新知