设计情势,Net下的观看者

上边是一些有关这么些Observer的大旨一些定义,在众多地方都能收看,这里作者归纳这这里便于未来翻看:

    记得已经写过风度翩翩篇关于(Observer方式卡塔尔(英语:State of Qatar),
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)之间的包扎並且在这里两以内创设少年老成种松耦合的关系。

图片 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

其中:

四、结构
图片 2 

ClassName是监听指标的现实性品种。(A,B,C,D它们都实现IActionListener那些接口的Run(卡塔尔(英语:State of Qatar)那个措施卡塔尔

五、Observer形式的多少个要点

Valid是是不是可行(二个标记属性)。

• 
使用面向对象的架空,Observer情势使得大家能够独自地退换目的与旁观者,进而使二者之间的依据关系达致松耦合。

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

• 
目的发送公告时,没有须求内定观看者,通告(可以指引公告音讯作为参数)会活动传播。观望者本人说了算是还是不是须要订阅文告,目的对象对此一无所
知。

上边用于监听的4个指标:A,B,C,D注册到上边包车型大巴MonitorFactory对象中去。当客户程序调用:

• 
在C#的event中,委托当作了望梅止渴的Observer接口,而提供事件的目的担任了对象对象。委托是比抽象Observer接口更为松耦合的宏图。

MonitorFactory.Publisher(new object());

 

管理进度:那么些对外宣布的Publisher方法被调用的时候,监听者会基于监听的项目自动的通告发出信任的其他对象。那样的客商程序就和事务逻辑完结了松耦合,减少了顾客程序和事情的注重性。顾客程序完全不掌握具体调用的是这几个措施,只担当向MonitorFactory发送音讯对象(这里是arg参数卡塔尔国,监听者就依照自个儿承担的音信自动的通知任何连锁的对象。

六、项目中使用的宣布订阅形式的莫过于例子:(这里其实利用了observer情势的恢弘卡塔尔(قطر‎供给是:当叁个目的的图景发生了转移(这里是传播贰个音信给一个对象卡塔尔国,那么全体监听这几个目的的别样对象会根据钦赐的抽出目的的种类调用钦定对象的章程:大家都很明亮的摸底到observer情势首若是用于当多个对象的事态发生变化的时候,会活动的文告订阅的此外对象,也正是说会把当下的音讯传递给其它对象开展管理。不过有叁个主题材料是,倘使别的对象收取到的音信是由约束的,像有些对象只可以取出钦命项目标音讯等,那样的话就供给在从前的observer格局上海展览中心开补缺:

图片 3图片 4Subject对象
 public class MonitorFactory
    {
        private static MonitorConfiguration configuration;
        static MonitorFactory()
        {
            configuration=ObjectXmlSerializer.LoadFromXml<MonitorConfiguration>(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, “Listener.xml”));
        }

上面是项目中有关这么些格局的的组织如图:

        /// <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;
        }      
    }

图片 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文件就是产生那三个职能,代码如下:

图片 6图片 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卡塔尔(英语:State of Qatar);//这里是调用钦赐对象的措施
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return result;
        }

 

图片 8图片 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文件来安插节点来促成,那样会越来越灵活

图片 10图片 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
* 《敏捷软件开采:原则、方式与实行》罗伯特C. Martin
* 《重构:修正既有代码的规划》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

相关文章