上一篇讲了策略模式。我又花了2星期时间把观察者模式好好的研究了一下。
观察者模式定义:有时又被称为发布(publish )-订阅(Subscribe)模式、模型-视图(View)模式、源-收听者(Listener)模式或从属者模式)是软件设计模式的一种。在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实现事件处理系统
个人理解:观察者模式,故名思议就是有一个人是消息源,其它的人是读者。消息源改变要即使通知这些读者。我认为它最大的作用就是把主题和观察者分开。这样编程的人只需要对其中的一个种类进行编程。下面给出观察者模式的常规UML类图:
这个类图表示的是最基本的观察者模式,在主题集成的类中,肯定有一个观察者列表。当有消息需要广播时,调用notifyObserver方法遍历观察者列表,调用他们自己的update()方法即可。
但是我现在用的是C#编程,这样一套架构在C#里显得非常浪费精力。我自己就用的是C#内部的EVENT事件完成的观察者模式。非常简单。
主题类
把你想做为主题的事件都放在这个类当中
public class Subject
{
/// <summary>
/// 数据存储转发事件
/// </summary>
public event Action<object> DataStorageRelay = (object obj) => { };
/// <summary>
/// 命令下发事件
/// </summary>
public event Action<IList<TcpSocketClient>> CommandSending = (IList<TcpSocketClient> list) => { };
/// <summary>
/// Socket绑定事件
/// </summary>
public event Func<byte[], string> SocketBinding = (byte[] byteAry) => { return ""; };
/// <summary>
/// 数据解析事件
/// </summary>
public event Action<byte[] , int , TcpSocketClient > DataAnalysis = (byte[] byteAry, int count, TcpSocketClient socketClient) => { };
/// <summary>
/// 数据存储转发的触发
/// </summary>
/// <param name="obj"></param>
public void DataStorageRelay_trigger(object obj)
{
DataStorageRelay(obj);
}
/// <summary>
/// 命令下发的触发
/// </summary>
/// <param name="list"></param>
public void CommandSending_trigger(IList<TcpSocketClient> list)
{
CommandSending(list);
}
/// <summary>
/// Socket绑定类的触发
/// </summary>
/// <param name="byteAry"></param>
/// <returns></returns>
public string SocketBinding_trigger(byte[] byteAry)
{
return SocketBinding(byteAry);
}
/// <summary>
/// 数据解析事件触发
/// </summary>
/// <param name="byteAry"></param>
public void DataAnalysis_trigger(byte[] byteAry, int count, TcpSocketClient socketClient)
{
DataAnalysis(byteAry, count, socketClient);
}
}
主题容器
public class GprsSpecialEquipment
{
Subject subject;
public GprsSpecialEquipment(Subject subjectTemp)
{ subject = subjectTemp}
public void DataSendingEpHandler()
{
while (true)
{
try
{
subject.DataStorageRelay (obj); //触发事件
}catch{}
Thread.Sleep(1000);
}
}
观察者类处理
public class DataStorageSE_Main
{
#region 存储入口
public static void DataStorageSE(object obj)
{
ISEFrame frame = obj as ISEFrame;
//符合字节流协议处理
if (frame.AVersion=="021301")
{
DataStorageSEV021301.DataStorageSEBranch(obj);
}
}
}
public class ProtocolPublicAttribute
{
#region 入口
public static string GetProtocolPublicAttribute(byte[] obj)
{
string version = ConvertData.ToHexString(obj, 0, 5);
if(version=="A55A021301")
{
byte[] sn = new byte[8]; //设备编号
Array.Copy(obj, 8, sn, 0, 8);
string EquipmentID = Encoding.ASCII.GetString(sn); //获取设备编号ASCII
return version + "&" + EquipmentID;
}
return "";
}
订阅主题
subject sub = new Subject();
sub.SocketBinding += ProtocolPublicAttribute.GetProtocolPublicAttribute;
sub.DataStorageRelay += DataStorageSE_Main.DataStorageSE;
GprsSpecialEquipment test = new GprsSpecialEquipment (sub );
自己的感悟:
针对于设计模式不是完全的模仿官方给出的类图进行实现和使用,而是要根据自己的应用场景找到最简单的使用方法。学习设计模式最重要的是给我们带来设计思想,编程思路上带来的改变。多动脑,多发散,多锻炼才能让咱们的程序扩展性更强。