设计模式-观察者模式
定义:对象间一种一对多的依赖关系,使得当一个对象改变状态,则所有依赖它的对象都会得到通知并自动更新。
使用场景:
(1)一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合
(2)一个对象通知其他对象,而并不知道这些对象是谁。
观察者模式类图如下
Subject 被观察者
定义被观察者必须实现的职责,它必须能够动态地增加,删除观察者,它一般是抽象类或者实现类,仅仅完成作为被观察者必须实现的职责,管理观察者并通知观察者。
ConcreteSubject 具体被观察者
定义被观察者自己的业务逻辑,同时定义对哪些事件进行通知。
Observer 观察者
观察者接收到消息后,对接收到的信息进行处理。
ConcreteObserver 具体的观察者
每个观察者在接收到消息后的处理是不同的,各观察者有自己的处理逻辑。
实例如下
汽车4S 店有销售经理、仓库经理,销售员。
当销售员卖出一辆车时需要通知销售经理和仓库经理。
(1) 通知销售经理自己卖了一辆车,销售经理需要给销售员添加绩效。
(2) 通知仓库经理要准备提车了,仓库经理从仓库中提取一辆车交付给客户。
代码实现如下
Observer 观察者
// 观察接口:Observer 观察者
public interface IObserver
{
// 销售信息通知
void SalesMessage(string msg);
}
ConcreteObserver 具体的观察者
// 销售经理:ConcreteObserver 具体观察者
public class SalesManager : IObserver
{
// 销售信息通知
public void SalesMessage(string msg)
{
Console.WriteLine("我是销售经理,恭喜{0},我要添加绩效", msg);
}
}
// 仓库经理:ConcreteObserver 具体观察者
public class WarehouseManager : IObserver
{
// 销售信息通知
public void SalesMessage(string msg)
{
Console.WriteLine("我是仓库经理,恭喜{0},我这就准备提取车辆 \n", msg);
}
}
Subject 被观察者
// 销售抽象类:Subject 被观察者
public abstract class ISale
{
// 保存所有观察者
protected List<IObserver> observerList = new List<IObserver>();
// 添加观察者
public void Attach(IObserver observer)
{
observerList.Add(observer);
}
// 删除观察者
public void Detach(IObserver observer)
{
observerList.Remove(observer);
}
}
ConcreteSubject 具体被观察者
// 销售员:ConcreteSubject 具体被观察者
public class Salesman : ISale
{
public Salesman()
{
}
// 卖出车辆
public void SaleCar(string name)
{
string msg = string.Format("小王卖了一辆{0}", name);
foreach(var observer in observerList)
{
observer.SalesMessage(msg);
}
}
}
代码调用如下
public class Client
{
public Client()
{
// 创建销售经理
SalesManager salesManager = new SalesManager();
// 创建仓库经理
WarehouseManager warehouseManager = new WarehouseManager();
// 创建销售员
Salesman salesman = new Salesman();
// 销售员添加销售经理作为观察者
salesman.Attach(salesManager);
// 销售员添加仓库经理作为观察者
salesman.Attach(warehouseManager);
salesman.SaleCar("奔驰 E300L");
salesman.SaleCar("奔驰 S300");
}
}
测试结果如下
优点:
(1) 观察者和被观察者是抽象耦合
(2) 建立一套触发机制
缺点:
(1) 目标与观察者之间的依赖关系并没有完全解除,而且有可能出现循环引用
(2) 当观察者对象很多时,通知的发布会花费很多时间,影响程序效率