设计模式之观察者模式(C#版)

设计模式之观察者模式(C#版)

简介

观察者模式是基于事件(event)或者委托(delegate)的。比如winform的控件事件OnXXXX,其实就是一种观察者模式。简单地说,观察者通过观察被观察者的行为而执行对应的动作。下面来进行一个假设吧。

假如你是个员工

我们用代码来模拟一个这样的场景。假如你是一个员工,同事们都跟你一样在偷懒,突然,老板回来了,这个时候,大家都要做回老板在的时候该做的事情(虽然老板不在也应该这样做),比如敲代码啊、写文案啊、做设计之类的咯(这里有程序员Jack、秘书小秘和文案小文)。下面我们来看一下模拟这个场景的极度耦合的代码

public abstract class Staff
{
	// 员工名
	protected string name;
	
	public Staff(string name)
	{
		this.name = name;
	}
	// 老板回来后做的事情
	public abstract void HandleBossComming();
}

// 老板的秘书
public class Secretary : Staff
{
	public Secretary(string name) : base(name) { }

	public override void HandleBossComming()
	{
		Console.WriteLine($"{name}正在给老板倒杯卡布奇诺");
	}
}

// 程序员
public class Programmer : Staff
{
	public Programmer(string name) : base(name) { }

	public override void HandleBossComming()
	{
		Console.WriteLine($"{name}假装在敲代码");
	}
}

// 文员
public class Clerk : Staff
{
	public Clerk(string name) : base(name) { }

	public override void HandleBossComming()
	{
		Console.WriteLine($"{name}停止玩手机");
	}
}

好了,员工都定义好了,也都实现了各自应对老板回来的策略。接下来,就是老板要回来了。

public class Boss
{
	public void Comming()
	{
		Programmer programmer = new Programmer("Jack");
		Secretary secretary = new Secretary("小秘");
		Clerk clerk = new Clerk("小文");

		// 员工们各自的反应
		programmer.HandlerBossComming();
		secretary.HandlerBossComming();
		clerk.HandlerBossComming();
	}
}

class Program
{
	static void Main(string[] args)
	{
		Boss boss = new Boss();
		boss.Comming();
    }
}

调用boss.Comming()方法后,在控制台就可以看到员工各自应对老板回来的策略。

Jack假装在敲代码
小秘正在给老板倒杯卡布奇诺
小文停止玩手机

功能实现得很完美啊,但是,之前也说了,这是极度耦合的一种实现方式,Boss类和Staff类耦合在一起了(纠缠在一起了),Boss类依赖了Staff类了(在Comming方法里面去实例化Staff,并调用他们的HandleBossComming方法),假如,公司又来了一个员工(假设他也会偷懒),那这里的代码就需要添加一个员工了。要解决这个问题,轮到观察者模式出现了。这里的观察者就是员工,被观察者就是老板啦(貌似正常应该是老板观察着员工吧,哈哈哈哈,偷懒的员工才需要观察老板)。

我们先定义对应的事件和委托来修改一下Boss类。

public class Boss
{
	// 老板来了对应事件的委托类型
	public delegate void EvenHandler();
	// 老板来了的事件
	public event EvenHandler OnComming;
	
	public void Comming()
	{
		// 发布老板来了这个事件
		OnComming?.Invoke();
	}
}

好了,现在老板回来这个事件已经定义好了,员工们(员工类)是不需要修改的,接下来要修改的部分,只是增加员工去观察(订阅)老板回来这个事件了。

class Program
{
	static void Main(string[] args)
	{
		Boss boss = new Boss();

		Programmer programmer = new Programmer("Jack");
		Secretary secretary = new Secretary("小秘");
		Clerk clerk = new Clerk("小文");
		
		// 员工们订阅老板回来这个事件
		boss.OnComming += programmer.HandleBossComming;
		boss.OnComming += secretary.HandleBossComming;
		boss.OnComming += clerk.HandleBossComming;
		// 老板回来了!
		boss.Comming();
	}
}

现在运行的结果和之前的是一样的啦。

Jack假装在敲代码
小秘正在给老板倒杯卡布奇诺
小文停止玩手机

现在的代码就解耦了,Boss类中的Comming方法里面只需要处理Boss自己的事情,不需要再去管Staff类的事情了。现在不管有多少个员工,只有有需要的才会去订阅老板回来这个事件。

现在呢,Jack和小文说,我们好像没有必要三个人都去观察着老板,要不,小秘,老板回来了由你来通知我们(同仇敌忾)?小秘说,好吧,毕竟我是最贴近老板的人。

那现在要对小秘也加个事件,让Jack和小文来订阅。

public class Secretary : Staff
{
	
	public delegate void BossComeHandler();
	public event BossComeHandler BossIsComming;
	public Secretary(string name) : base(name) { }

	public override void HandleBossComming()
	{
		Console.WriteLine($"{name}正在给老板倒杯卡布奇诺");
		BossIsComming();
	}
}

现在Jack和小文只要等小秘告诉他们就好了

class Program
{
	static void Main(string[] args)
	{
		Boss boss = new Boss();

		Programmer programmer = new Programmer("Jack");
		Secretary secretary = new Secretary("小秘");
		Clerk clerk = new Clerk("小文");
		
		// 员工们订阅老板回来这个事件
		boss.OnComming += secretary.HandleBossComming;
		// Jack和小文订阅小秘告知老板来了的事件
		secretary.BossIsComming += programmer.HandleBossComming;
		secretary.BossIsComming += clerk.HandleBossComming;
		
		// 老板回来了!
		boss.Comming();
	}
}

通过小秘来告诉Jack和小文的这种形式有什么好处呢?处理老板来了,在这里只是让小秘发布一个BossComeHandler事件,但实际小秘还可以定义和发布多个事件(定义不同的委托事件),通过小秘,可以减少Boss类上面的事件定义,让Boss只负责发布回来了的这个消息。

总结

观察者模式通过委托事件,让类通过事件的发布和订阅的方式来实现方法的调用,这样既降低了类之间的耦合,也可以使代码更容易扩展。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值