Net下的旁观者,设计情势

上面是一些有关那些Observer的为主一些概念,在大多地方都能观望,这里本身总结那这里便于现在翻看:

    记得已经写过一篇有关(Observer方式),
http://www.cnblogs.com/Charles2008/archive/2008/10/06/1305116.html 

一、公布订阅模型(pub-sub)

布告/订阅简称(Pub/Sub)格局,这种Pub/Sub设计形式是observer的一种变体。Observer方式在Design
patterns用于:二个对象(Observer)观望者被注入到另一个对象(主旨Subject),用于监听事件,观看者(Observer)暗中地显示(核心Subject)的变迁。publish/subscribe方式在核心(subject)和观望者(observer)之间增添了一层间隔。
这一个层移除了在观望者(observer)和重心(subject)之间的包扎并且在这两之内创设一种松耦合的涉及。

爱博体育app下载 1

Pub格局重如果负担向外发送新闻,Sub首要是订阅音信。主要用以“只负担传递音讯,并不爱慕别的对象已经接收那一个音信”.

二、动机(Motivation)

上边是采纳Pub/Sub这种设计形式场景:

在软件创设进程中,大家须求为一些对象创建一种 “布告重视关系”
——两个目的(目的对象)的动静发生变动,全数的借助对象(观察者对象)都将得
到公告。借使如此的借助关系过度紧凑,将使软件不能很好地抵抗变化。

在切实的职业管理中,往往会有那般的需要:非常是应用系统须要改换和置换数据,必得传递那些改动的数码(DomainModel)交给工作逻辑层进行拍卖。极其是两个模块须要这种多少同步和谐时,就足以用Pub/Sub这种设计情势来缓和难题。

动用面向对象手艺,能够将这种借助关系弱化,并转身一变一种和谐的依赖关系。进而实现软件体系结构的松耦合。

实惠:减少了应用程序和业务逻辑的耦合,统一的对外Publisher(发布),收缩了信赖。让大家只关心监听者监听的档期的顺序。而不需驾驭具体该哪三个类来拍卖该新闻.上边的安插文件是监听器对象,通过配备显得愈加灵敏。(Listener.xml文件)

三、意图(Intent)

<?xml version=”1.0″?>
<MonitorConfiguration xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:xsd=”http://www.w3.org/2001/XMLSchema"&gt;
  <Listeners>
    <Listener classname=”Listener.A” valid=”true” ListenerType=”System.Object” />
    <Listener classname=”Listener.B” valid=”true” ListenerType=”System.Object” />
    <Listener classname=”Listener.C” valid=”true” ListenerType=”System.Object” />
    <Listener classname=”Listener.D” valid=”true” ListenerType=”System.Object” />
  </Listeners>
</MonitorConfiguration>

概念对象间的一种一对多的注重关系,以便当多少个对象的情景发生变动时,全部重视于它的对象都赢得照望并自动更新   
——《设计情势》GoF

其中:

四、结构
爱博体育app下载 2 

ClassName是监听指标的有血有肉项目。(A,B,C,D它们都落到实处IActionListener这几个接口的Run()那么些办法)

五、Observer格局的几当中央

Valid是是还是不是行得通(贰个标识属性)。

• 
使用面向对象的虚幻,Observer方式使得大家得以单独地转移指标与阅览者,进而使二者之间的正视关系达致松耦合。

ListenerType是监听目的监听音信的类型。

• 
目的发送通告时,没有要求钦定观望者,文告(能够辅导通告音信作为参数)会自行传播。观看者本身支配是不是供给订阅公告,指标对象对此一无所
知。

上边用于监听的4个对象:A,B,C,D注册到下边包车型地铁MonitorFactory对象中去。当客商程序调用:

• 
在C#的event中,委托充当了抽象的Observer接口,而提供事件的靶子担负了指标对象。委托是比抽象Observer接口更为松耦合的布置性。

MonitorFactory.Publisher(new object());

 

管理进程:那么些对曾外祖父布的Publisher方法被调用的时候,监听者会基于监听的品类自动的公告发出信赖的别样对象。那样的顾客程序就和事务逻辑完结了松耦合,降低了顾客程序和事务的正视性。客商程序完全不知器具体调用的是那多少个方法,只担当向MonitorFactory发送音讯对象(这里是arg参数),监听者就依附本身接受的新闻自动的公告别的相关的对象。

六、项目中选拔的公布订阅方式的实际例子:(这里其实利用了observer方式的恢弘)必要是:当贰个指标的境况爆发了转移(这里是传播三个音讯给叁个指标),那么富有监听那一个目的的别的对象会根据钦定的吸取目的的花色调用钦命对象的方式:大家都很理解的摸底到observer情势重若是用于当贰个目的的气象爆发变化的时候,会活动的通知订阅的其他对象,也正是说会把当下的音讯传递给另外对象开展拍卖。然则有贰个主题材料是,要是别的对象吸取到的消息是由限制的,像某些对象只好抽取钦命项目标新闻等,那样的话就需求在在此以前的observer情势上开展补给:

爱博体育app下载 3爱博体育app下载 4Subject对象
 public class MonitorFactory
    {
        private static MonitorConfiguration configuration;
        static MonitorFactory()
        {
            configuration=ObjectXmlSerializer.LoadFromXml<MonitorConfiguration>(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, “Listener.xml”));
        }

爱博体育app下载,下边是项目中有关这一个方式的的布局如图:

        /// <summary>
        /// 对外发表数量
        /// </summary>
        /// <param name=”arg”></param>
        public static bool Publisher(object arg)
        {
            bool result = false;
            if (configuration != null && configuration.Listeners != null && configuration.Listeners.Count > 0)
            {
                IActionListener listener = null;
                foreach (ListenerItem item in configuration.Listeners)
                {
                    if (item.Valid)
                    { 
                        listener = (IActionListener)Activator.CreateInstance(Type.GetType(item.ClassName));
                        if (listener != null)
                        {
                            if (string.IsNullOrEmpty(item.ListenerType))
                            {
                                listener.Run(arg);
                            }
                            else
                            {
                                if (item.ListenerType == arg.GetType().FullName)
                                {
                                    listener.Run(arg);
                                }
                            }
                        }
                    }
                }
            }
            return result;
        }      
    }

爱博体育app下载 5

以上是私家对Pub/Sub这种设计方式的明白,倘使有怎么样驾驭不得法的地点,还请朋友们多多指教。

第一来探视Listener文件夹下的三个文本(其余多少个文件类似)

Best Regards,

    [KnowType(typeof(float))]
    public class DesignApprovalListener:IActionListener
    {
         public bool Run(object value)
        {
            return true;
        }
    }

Charles Chen

其间KnowType是三个自定义的属性,代码如下:

Email: gotosunny@msn.com

  [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
    public class KnowTypeAttribute : Attribute
    {
        private string m_typeName;

        public string TypeName
        {
            get { return m_typeName; }
        }

        public KnowTypeAttribute(Type modelType)
        {
            this.m_typeName = modelType.FullName;
        }
    }

 

IActionListener是一个接口:

   public interface IActionListener
    {
        /// <summary>
        /// 订阅接受方法
        /// </summary>
        /// <param name=”value”>Domain Model or Data Entity</param>
        /// <returns>实施成功重临True,不然为false</returns>
        bool Run(object value);
    }

 

在那之中的主干措施是透过反射获得全体监听的指标所急需承受对象的门类,那样就能够调用钦点对象的不二诀窍,实际不是调用全体监听者的情势:上面是这么些措施的着力:

Core文件夹下的MonitorFactory.cs文件正是实现那二个作用,代码如下:

爱博体育app下载 6爱博体育app下载 7Code
 public static bool Publisher(object arg)
        {
            bool result = false;
            if (configuration != null && configuration.Listeners != null && configuration.Listeners.Count > 0)
            {
                RegisteredListener listener = null;
                foreach (ListenerItem item in configuration.Listeners)
                {
                    if (item.Valid)
                    {
                        listener = ActivatorListener(item.ClassName);
                        if (listener != null)
                        {
                            if (listener.RegisteredTypes == null || listener.RegisteredTypes.Length == 0)
                            {
                               result= listener.CurrentListener.Run(arg);
                            }
                            else
                            {
                                foreach (KnowTypeAttribute attributeItem in listener.RegisteredTypes)
                                {
                                    if (arg.GetType().FullName == attributeItem.TypeName)
                                    {
                                        result=listener.CurrentListener.Run(arg);//这里是调用钦赐对象的不二法门
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return result;
        }

 

爱博体育app下载 8爱博体育app下载 9Code
  /// <summary>
        /// 创立Listener实例并获得Attribute
        /// </summary>
        /// <param name=”className”></param>
        /// <returns></returns>
        private static RegisteredListener ActivatorListener(string className)
        {
            RegisteredListener result = null;
            if (registeredContainer.ContainsKey(className))
            {
                result = registeredContainer[className];
            }
            else
            {
                Type type = Type.GetType(className);
                if (type != null)
                {
                    KnowTypeAttribute[] registerType = type.GetCustomAttributes(typeof(KnowTypeAttribute), false) as KnowTypeAttribute[];
                    IActionListener listenerInstance = Activator.CreateInstance(type) as IActionListener;
                    result = new RegisteredListener(listenerInstance, registerType);
                    registeredContainer.Add(className, result);
                }
            }
            return result;
        }

 

登记监听目标目标是经过代码钦命的,当然能够经过贰个xml文件来配置节点来完结,那样会越来越灵敏

爱博体育app下载 10爱博体育app下载 11Code
        private static Dictionary<string, RegisteredListener> registeredContainer;
        private static MonitorConfiguration configuration;
        static MonitorFactory()
        {
            configuration = new MonitorConfiguration();
            configuration.Listeners = new List<ListenerItem>();

            ListenerItem item = new ListenerItem();
            item.ClassName = “ProjectEstablishRequestListener”;
            configuration.Listeners.Add(item);
            item = new ListenerItem();
            item.ClassName = “ProjectApprovalListener”;
            configuration.Listeners.Add(item);
            item = new ListenerItem();
            item.ClassName = “DesignApprovalListener”;
            configuration.Listeners.Add(item); 
            
            registeredContainer = new Dictionary<string, RegisteredListener>();
            foreach (ListenerItem listener in configuration.Listeners)
            {
                if (listener.Valid)
                {
                    ActivatorListener(listener.ClassName);
                }
            }
        }

这里就不出示别的代码了,不问可见看法正是那样,通过在Listener的类公事中经过品质来制定那几个目的接受的音讯类型,最终遍历全部的监听者对象看是不是满意内定的新闻类型,最后调用钦赐的对象的主意。这样就达成了种类中的必要。

引入能源
* 《设计方式:可复用面向对象软件的功底》GoF
* 《面向对象剖析与规划》Grady
Booch
* 《敏捷软件开拓:原则、格局与执行》RobertC. 马丁
* 《重构:改正既有代码的统一图谋》MartinFowler
* 《Refactoring to Patterns》Joshua Kerievsky
 更多MSDN资源
* MSDN普通话网站
http://www.microsoft.com/china/msdn 
* MSDN中文网络广播
http://www.msdnwebcast.com.cn/
* MSDN Flash
http://www.microsoft.com/china/newsletter/case/msdn.aspx 
* MSDN开采宗旨
http://www.microsoft.com/china/msdn/DeveloperCenter/default.mspx

相关文章