一、概念
①、什么是观察者模式?
定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通过所有观察者对象,使它们能够自动更新自己。
②、主要解决什么问题?
一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。
③、如何解决?
使用面向对象技术,可以将这种依赖关系弱化。
④、何时使用?
一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播等通知。
⑤、使用场景?
一个抽象模型有两个方面,其中一个方面依赖另一个方面,将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
一个对象必须通知其他对象,而并不知道这些对对象是谁。
⑥、有缺点?
优点:
1、观察者和被观察者是抽象耦合的。
2、建立一套触发机制。
缺点:
1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
二、图
①、结构图
②、拓展图
三、代码
①、代码类图
②、代码
客户端
class Program
{
static void Main(string[] args)
{
Boss huhansan = new Boss(); //用Boss类实例化一个huhansan对象
StockObserver tongshi1 = new StockObserver("乔巴", huhansan); //用StockObserver类实例化一个tongshi1对象(创建的这个对象名称为乔巴,与huhansan是依赖关系)
NBAObserver tongshi2 = new NBAObserver("Jason", huhansan); //用NBAObserver类实例化一个tongshi2对象(名字为Jason,与通知者huhansan建立关联)
//将不同类的不同方法委托给“老板”类的“更新”上了
huhansan.Update += new EventHandler(tongshi1.CloseStockMarket); //将“看股票者”的“关闭股票程序”方法挂钩到老板huhansan 的更新上
huhansan.Update += new EventHandler(tongshi2.CloseNBADirectSeeding);
huhansan.SubjectState = "我胡汉三又回来了"; //通知者的通知内容
huhansan.Notify(); //向名单内人员发送通知内容
Console.Read();
}
private static void Huhansan_Update()
{
throw new NotImplementedException();
}
}
委托
delegate void EventHandler(); //声明一个委托,名称叫“EventHandler(事件处理程序)”,无参数,无返回值
老板类
class Boss : Subject
{
public event EventHandler Update; //声明一个时间Update,类型为委托EventHandler
private string action;
public void Notify()
{
Update(); //在访问通知方法时,调用更新
}
public string SubjectState
{
get { return action; }
set { action = value; }
}
}
前台秘书类
class Secretary : Subject
{
public event EventHandler Update;
private string action;
public void Notify()
{
Update();
}
public string SubjectState
{
get { return action; }
set { action = value; }
}
}
看股票的同事
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}关闭股票行情,继续工作!", sub.SubjectState, name);
}
}
看NBA的同事
class NBAObserver
{
private string name;
private Subject sub;
public NBAObserver(string name, Subject sub)
{
this.name = name;
this.sub = sub;
}
public void CloseNBADirectSeeding()
{
Console.WriteLine("{0} {1}关闭NBA直播,继续工作!", sub.SubjectState, name);
}
}
四、拓展
C#中List与IList的区别
https://blog.csdn.net/bear_79/article/details/52039199