简介:
本篇文章先介绍察者模式,并简述其作用,然后是一个基于apex游戏的小例子和代码实现,所采用的编程语言是C#
什么是观察者模式:
观察者模式就是一种设计模式,它允许一个对象通知多个观察者对象,当对象达到触发条件时观察者会做出相应的改变。(举个例子在apex里如果角色被人攻击了,队友会听到角色被攻击的语音提示。在这里角色就是对象,队友就是观察者)
观察者模式有什么用?值不值得学?
用处:
(1)GUI图形界面设计,如果你拖动按钮并编写相应的触发事件,然后你会发现你点一下按钮,事件就触发了。你可能会说这不是理所当然吗?可是计算机很笨它可不会觉得这理所当然,实际上它的底层就是观察者模式,只是别人帮你写好了而已。
(2)订阅系统的实现,比如逛B站的你如果关注过某个up主,那么当up主更新了一个视频,你会立刻接收到通知,不订阅的就不会收到。为什么up主一发视频你就能收到通知呢?观察者模式,你在观察up主。
值不值得学:
这是诸多设计模式里面应用场景最多的一类,面试的时候如果要考你设计模式,大概率你会遇见它,并且它确实是一种有用的思维,所以我认为可以学(当然,看你心情)。
apex游戏实例:
现在来实现一个这样的场景,你和你的两个大佬朋友一起打排位,你看见一个独狼直接(相信众神之父!)然后(我重伤倒地,需要帮助!)。你的两个大佬朋友看见你需要帮助,立马跑过来两条枪线击毙敌人。
OK,场景有了现在来分析一下,在上面场景中哪里体现了观察者模式,很明显当你倒地的时候你的两个大佬朋友收到了通知前来帮你。
那么是大佬在观察你吗?逻辑上如此实现起来却不行,比如说如果是大佬被对面打倒然后大喊一丝一丝全部一丝,那现在就是你在观察大佬,逻辑上就出问题了。所以需要一个额外的观察者类,让它来进行通知,在游戏中这是游戏服务器的工作。
分析完场景后得出以下结果,需要一个英雄类作为观察者,需要一个游戏服务器类来完成通知的功能。
为了这个设计模式的完整性我添加了抽象游戏服务器类和一个IObserver类接口,如果你一开始不理解没有关系,后面我会进行一点扩展,你就明白了。(提示一下即使不添加这两个抽象层,也是可以实现观察者模式的,但是可扩展性会很差)
下面是这个场景设计的类图:
IObserver是接口,它包含了一个角色的一些基本方法和名字,但是都没有实现
Legend是实现了IObserver接口的类
GameServer是一个抽象类,它包含了虚方法(就是定义了但是不实现的方法啦)Notify(),它与IObserver的关系是聚合关系在GameServer中有一个包含了IObserver的列表Team
EAServer类是继承自GameServer的类,在EAServer中实现了Notify方法
所有的代码:
IObserver类:
namespace Apex观察者
{
public interface IObserver
{
string Name { get; set;}
void GoGoGo()
{
}
void Help()
{
}
}
}
Legend类:
//具体观察者
namespace Apex观察者
{
public class Legend : IObserver
{
private string name;
public Legend(string name)
{
this.name = name;
}
public string Name { get { return name; } set { name = value; } }
//重伤倒地了,呼叫所有队友前来帮助
public void GoGoGo(GameServer gameServer)
{
Console.WriteLine("{0}:相信众神之父! 我重伤倒地,需要帮助!",name);
gameServer.Notify(name);
}
public void Help()
{
Console.WriteLine("{0}:正在前往支援!,目标倒地!",name);
}
}
}
GameServer类
//抽象类,抽象目标类
namespace Apex观察者
{
public abstract class GameServer
{
public List<IObserver> _team = new List<IObserver>();
public void Join(IObserver observer)
{
_team.Add(observer);
Console.WriteLine("{0},加入小队",observer.Name);
}
public void Quit(IObserver observer)
{
_team.Remove(observer);
Console.WriteLine("{0},退出小队", observer.Name);
}
public abstract void Notify(string name);
}
}
EAServer类
//具体目标
namespace Apex观察者
{
class EAServer : GameServer
{
//重写Notify方法,实现对每个观察者的通知
public override void Notify(string name)
{
//遍历判断,如果相等就通知
foreach (var item in _team)
{
if (!item.Name.Equals(name)) { item.Help(); }
}
Console.WriteLine("敌方小队已被全灭,这个维度前景不错");
Console.WriteLine("{0}:虽然我很弱,但是我的队友很强啊!", name);
}
}
}
执行主程序:
using Apex观察者;
class Program
{
static void Main(string[] args)
{
//创建3个具体观察者
var LegendA = new Legend("双锤骷髅海地平线");
var LegendB = new Legend("光头恶灵");
var LegendC = new Legend("kd0.5的我");
//创建一个具体实现类
GameServer gameServer = new EAServer();
//3个观察者入队
gameServer.Join(LegendA);
gameServer.Join(LegendB);
gameServer.Join(LegendC);
Console.WriteLine();
//触发观察条件
LegendC.GoGoGo(gameServer);
}
}
运行结果:
扩展:
如果你能读到这里我相信你已经基本了解了什么叫观察者模式以及如何实现,现在来谈谈为什么要添加抽象层GameServer和IObserver。
举个例子当角色倒地不同队友通报的语音不同,这该怎么办,这个时候就需要定义多个具体观察者类比如LegendA,LegendB,LegendC它们都实现观察者接口,再在各个类中实现接口中的方法,这样不同的角色可以通报不同的语音,并且它们不是同一个类却可以相互通知。抽象目标类也是一个道理,很多时候不止一种通知服务,可能倒地会让队友来救,发现好东西也可以让队友来拿等等。
如果你有兴趣可以分别设计多个具体观察者类和具体实现类。具体的应用要看场景,没有抽象层也是可以实现的,设计模式是一种思维重在学习如何使用它。