实现方式
- 同步划分:同步阻塞、异步非阻塞
- 线程划分:线程内的、跨线程的
原理及应用场景
观察者模式(Observer Design Pattern)也被称为发布订阅模式(Publish-Subscribe Design Pattern)
,它的定义是这样的:
在对象之间定义一个一对多的依赖,当一个对象状态改变的时候,所有依赖的对象都会自动收到通知。
核心概念: 被观察者、观察者 Subject、Observer Producer、Consumer EventEmitter、EventListener Dispatcher、Listener
实现一个一对一的依赖
//在对象之间定义一个一对多的依赖,当一个对象状态改变的时候,所有依赖的对象都会自动收到通知。
public class Class1
{
public static void Main(string[] args)
{
Subject subject = new Subject();
subject.notify();
}
}
public class Subject{
private static Observer observer = new Observer();
public void notify() {
observer.update();
}
}
public class Observer
{
public void update()
{
Console.WriteLine("观察者更新行为被触发");
}
}
最经典的实现方式
public class Class1
{
public static void Main(string[] args)
{
Subject subject = new Subject();
subject.RegisterObserver(new ObserverA());
subject.RegisterObserver(new ObserverB());
subject.notifyObserver(null);
}
}
public class Subject{
private static List<Observer> list = new List<Observer>();
public void RegisterObserver(Observer observer) {
list.Add(observer);
}
public void RemoveObserver(Observer observer) {
list.Remove(observer);
}
public void notifyObserver(Message message) {
foreach (var item in list)
{
item.update(message);
}
}
}
public class Message {
public string content;
}
public interface Observer
{
void update(Message message);
}
public class ObserverA:Observer
{
public void update(Message message)
{
Console.WriteLine("观察者A更新行为被触发");
}
}
public class ObserverB: Observer
{
public void update(Message message)
{
Console.WriteLine("观察者B更新行为被触发");
}
}
案例: 假设我们在开发一个 P2P 投资理财系统,用户注册成功之后,我们会给用户发放投资体验金。代码实现大致是下面这个样子的:
public class UserController
{
private IUserService userService;
private IPromotionService promotionService;
public UserController(IUserService userService, IPromotionService promotionService)
{
this.userService = userService;
this.promotionService = promotionService;
}
public long register(string telephone, string password)
{
//省略输入参数的校验代码
//省略userService.register()异常的try-catch代码
long userId = userService.register(telephone, password);
promotionService.issueNewUserExperienceCash(userId);
return userId;
}
}
public interface IUserService {
long register(string telephone, string password);
}
public interface IPromotionService {
void issueNewUserExperienceCash(long userId);
}
虽然注册接口做了两件事情,注册和发放体验金,违反单一职责原则,但是,如果没有扩展和修改的需求,现在的代码实现是可以接受的。如果非得用观察者模式,就需要引入更多的类和更加复杂的代码结构,反倒是一种过度设计。
相反,如果需求频繁变动,比如,用户注册成功之后,不再发放体验金,而是改为发放优惠券,并且还要给用户发送一封“欢迎注册成功”的站内信。这种情况下,我们就需要频繁地修改 register() 函数中的代码,违反开闭原则。而且,如果注册成功之后需要执行的后续操作越来越多,那 register() 函数的逻辑会变得越来越复杂,也就影响到代码的可读性和可维护性。
这个时候,观察者模式就能派上用场了。利用观察者模式,我对上面的代码进行了重构。重构之后的代码如下所示:
public class UserController
{
private IUserService userService;
private List<RegObserver> regObservers = new List<RegObserver>();
public UserController(IUserService userService)
{
this.userService = userService;
}
public void setRegObservers(List<RegObserver> observers) { regObservers.AddRange(observers); }
public long register(string telephone, string password)
{
//省略输入参数的校验代码
//省略userService.register()异常的try-catch代码
long userId = userService.register(telephone, password);
foreach (RegObserver item in regObservers)
{
item.handleRegSuccess(userId);
}
return userId;
}
}
public interface RegObserver {
void handleRegSuccess(long userId);
}
public class RegNotificationObserver : RegObserver
{
public void handleRegSuccess(long userId)
{
throw new NotImplementedException();
}
}
public class RegPromotionObserver : RegObserver
{
private IPromotionService promotionService;
public RegPromotionObserver(IPromotionService promotionService)
{
this.promotionService = promotionService;
}
public void handleRegSuccess(long userId)
{
promotionService.issueNewUserExperienceCash(userId);
}
}
public interface IUserService {
long register(string telephone, string password);
}
public interface IPromotionService {
void issueNewUserExperienceCash(long userId);
}