目录
一、观察者模式
观察者模式实现了观察者与目标之间的抽象耦合、动态联动。
例如 知乎、微博、外卖等软件,当有新的热门信息、我们经常浏览的信息更新时,手机上经常会受到信息。我们就是观察者,而这些软件就像是目标。当信息更新时,我们会接受到提示信息,当我们取消一些订阅时,一些信息就不会被推送。
本质是触发联动
别名:
1、发布-订阅模式
2、模型-视图模式
3、源-监听器模式
4、从属者模式
模式如其名。
二、观察者模式角色
1、抽象主题
一个目标可以被多个观察者观察,下面的例子中的员工--老板就是n--1;
目标提供对观察者的增加和删除,如下文中的subject。
当目标的状态发生变化时,目标负责通知所有现存的观察者。
2、抽象观察者
为所有的具体观察者提供一个接口。
有一个更新接口,方便更新新的信息。
3、具体主题
将有关状态存入具体观察者对象。在状态发生变化时,负责给所有所属的观察者发送消息。
因此又被叫做具体被观察者角色。
4、具体观察者
要实现具体更新接口。
还可以有一个指向具体主题对象的引用。
如下文中的Stock和Dba。
四、应用
使系统耦合度降低,便于复用。
要使低耦合度的对象能协调工作。
五、代码实例一
同事间帮忙。
第一个类:抽象主题类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 观察者模式__通知信息
{
interface Subject
{
void Attach(Observer obs);
void Detach(Observer obs);
void Notify();
String SubjectState
{
get;
set;
}
}
}
第二个类:抽象观察者
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 观察者模式__通知信息
{
abstract class Observer
{
protected string name;
protected Subject sub;
protected Observer(string name, Subject sub)
{
this.name = name;
this.sub = sub;
}
public abstract void update();
}
}
第三个类:具体主题类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 观察者模式__通知信息
{
class Subject_Secretary : Subject
{
private IList<Observer> observers = new List<Observer>();
private string action;
public string SubjectState
{
get { return action; }
set { action = value; }
}
public void Attach(Observer obs)
{
observers.Add(obs);
}
public void Detach(Observer obs)
{
observers.Remove(obs);
}
public void Notify()
{
foreach(Observer o in observers)
{
o.update();
}
}
}
}
第四、五个类:具体观察者类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 观察者模式__通知信息
{
class Stock_Observer : Observer
{
public Stock_Observer(string name, Subject sub) : base(name, sub) { }
public override void update()
{
Console.WriteLine("{0}{1}关闭股票,继续工作", sub.SubjectState, name);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 观察者模式__通知信息
{
class Nba_Observer : Observer
{
public Nba_Observer(string name, Subject sub) : base(name, sub) { }
public override void update()
{
Console.WriteLine("{0}{1}停止看球,继续工作", sub.SubjectState, name);
}
}
}
测试类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 观察者模式__通知信息
{
class Program
{
static void Main(string[] args)
{
Subject_Secretary L1 = new Subject_Secretary();
Stock_Observer S1 = new Stock_Observer("S1",L1);
Nba_Observer N1 = new Nba_Observer("N1", L1);
L1.Attach(S1);
L1.Attach(N1);
L1.SubjectState = "老板来了";
L1.Notify();
}
}
}
六、代码实例二
一个股票的例子
第一个类:一个抽象的股票类
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 观察者模式__股票行情
{
abstract class Stock
{
protected string symbol;
protected double price;
private ArrayList investors = new ArrayList();
protected Stock(string symbol, double price)
{
this.symbol = symbol;
this.price = price;
}
public void Attach(IInvestor inv)
{
investors.Add(inv);
}
public void Detach(IInvestor inv)
{
investors.Remove(inv);
}
public void Notify()
{
foreach(IInvestor i in investors)
{
i.update(this);
}
}
public double Price
{
get { return price; }
set { price = value; Notify(); }
}
public string Symbol
{
get { return symbol; }
set { symbol = value; }
}
}
}
第二个类:观察者接口
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 观察者模式__股票行情
{
interface IInvestor
{
void update(Stock stock);
}
}
第三个类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 观察者模式__股票行情
{
class Investor_One : IInvestor
{
private string name;
private string ObserveState;
private Stock stock;
public Investor_One(string name)
{
this.name = name;
}
public void update(Stock stock)
{
Console.WriteLine("Notified investor {0} of {1}'s change to {2:C}", name, stock.Symbol, stock.Price);
}
public Stock Stock
{
get { return stock; }
set { stock = value; }
}
}
}
第四个类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 观察者模式__股票行情
{
class IBM:Stock
{
public IBM(string symbol,double price):base(symbol, price) { }
}
}
第五个测试类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 观察者模式__股票行情
{
class Program
{
static void Main(string[] args)
{
Investor_One i1 = new Investor_One("i1");
Investor_One i2 = new Investor_One("i2");
IBM ibm = new IBM("IBM", 200.1);
ibm.Attach(i1);
ibm.Attach(i2);
ibm.Price = 201;
ibm.Price = 101.9;
}
}
}
七、C#中的委托事件机制
delegate void UpdateDelegate()是定义一个委托,下面两个观察者的更新函数都符合这个委托。
public event UpdateDelegate UpdateHandler定义事件,一旦事件被触发,就会调用一组 UpdateDelegate()规范的方法。
+号就可以实现添加事件功能。
UpdateHandler不为空时,代表有订阅者,就会调用UpdateHandler()
主题类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 观察者模式__委托
{
delegate void UpdateDelegate();//委托对象
class Subject
{
public event UpdateDelegate UpdateHandler;
public void Attach(UpdateDelegate ud)
{
UpdateHandler += ud;
}
public void Detach(UpdateDelegate ud)
{
UpdateHandler -= ud;
}
public void Notify()
{
if (UpdateHandler != null)
UpdateHandler();//委托事件
}
}
}
真实主题类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 观察者模式__委托
{
class ConcreteSubject:Subject
{
private string subjectState;
public string SubjectState
{
get { return subjectState; }
set { subjectState = value; }
}
}
}
观察者类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 观察者模式__委托
{
class ConcreteObserver
{
private string name;
private string observerState;
private ConcreteSubject subject;
public ConcreteObserver(string name, ConcreteSubject subject)
{
this.name = name;
this.subject = subject;
}
public void update()
{
observerState = subject.SubjectState;
Console.WriteLine("observer {0} s new state is{1}", name, observerState);
}
public ConcreteSubject Subject
{
get { return subject; }
set { subject = value; }
}
}
}
另一个观察者类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 观察者模式__委托
{
class ConcreteObserver_Another
{
public void show()
{
Console.WriteLine("AnotherObserver got an Notification!");
}
}
}
测试类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 观察者模式__委托
{
class Program
{
static void Main(string[] args)
{
ConcreteSubject cs = new ConcreteSubject();
ConcreteObserver c1 = new ConcreteObserver("c1",cs);
ConcreteObserver c2 = new ConcreteObserver("c2", cs);
ConcreteObserver_Another c3 = new ConcreteObserver_Another();
cs.Attach(new UpdateDelegate(c1.update));
cs.Attach(new UpdateDelegate(c2.update));
cs.Attach(new UpdateDelegate(c3.show));
cs.SubjectState = "啊哈哈哈哈";
cs.Notify();
Console.WriteLine("------------");
cs.Detach(new UpdateDelegate(c3.show));
cs.Notify();
}
}
}
猫大叫一声,所有的老鼠都开始逃跑,主人被惊醒。
代码实例:
抽象主题:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ObserverOne
{
abstract class Subject
{
public string State { get ; set ; }
abstract public void Attach(UpdateDelegate a);
abstract public void Detach(UpdateDelegate a);
abstract public void Notify();
}
}
具体主题:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ObserverOne
{
delegate void UpdateDelegate();
class CatSubject:Subject
{
private string state;
public event UpdateDelegate UpdateHandler;
public string State { get => state; set => state = value; }
public override void Attach(UpdateDelegate a)
{
UpdateHandler += a;//---
}
public override void Detach(UpdateDelegate a)
{
UpdateHandler -= a;
}
public override void Notify()
{
if (UpdateHandler != null) UpdateHandler();
}
}
}
抽象观察者:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ObserverOne
{
abstract class ObserverPlus
{
protected string name;
protected Subject subject;
protected ObserverPlus(string name, Subject subject)
{
this.name = name;
this.subject = subject;
}
public abstract void update();
}
}
具体:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ObserverOne
{
class MouseObserverPlus : ObserverPlus
{
private CatSubject c = new CatSubject();
public MouseObserverPlus(string name,CatSubject subject) : base(name, subject) { c = subject; }
public override void update()
{
Console.WriteLine("{0}....{1}来了快跑!", c.State,name);
// Console.WriteLine(subject.State+"---");
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ObserverOne
{
class PersonObserver : ObserverPlus
{
private CatSubject c=new CatSubject();
public PersonObserver(string name,CatSubject subject) : base(name, subject) { c = subject; }
public override void update()
{
Console.WriteLine("{0}....来了{1}惊醒了!", c.State, name);
}
}
}
测试:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ObserverOne
{
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
//CatSubject cat = new CatSubject();
//MouseObserver m1 = new MouseObserver("Tom", cat);
//cat.Attach(new UpdateDelegate(m1.update));
//cat.State = "猫马上来";
//cat.Notify();
//cat.State = "猫来了";
//cat.Notify();//-----//-----//-----//----
CatSubject cat = new CatSubject();
MouseObserverPlus m1 = new MouseObserverPlus("猫", cat);
cat.Attach(new UpdateDelegate(m1.update));
cat.State = "马上";
cat.Notify();
cat.State = "现在";
cat.Notify();
PersonObserver p1 = new PersonObserver("小明", cat);
cat.Attach(new UpdateDelegate(p1.update));
cat.Notify();
}
}
}