C++一举手一投足项目开销笔记(.Net下的观看者(Observer)形式)

下边是局地有关那些Observer的基本一些定义,在诸多地点都能看出,那里本人总结那那里便于未来翻看:

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

C++ 1

二、动机(Motivation)

在软件营造过程中,我们需求为一些对象建立一种 “布告重视关系”
——四个对象(目标对象)的情形发生变动,全数的依靠对象(观看者对象)都将得
到通报。如若这么的注重性关系过度紧密,将使软件不能够很好地抵抗变化。

接纳面向对象技术,能够将那种注重关系弱化,并摇身一变一种祥和的依靠关系。从而达成软件种类结构的松耦合。

三、意图(Intent)

概念对象间的一种一对多的依靠关系,以便当二个目的的情事发生转移时,全数正视于它的靶子都得到布告并自动更新   
——《设计形式》GoF

四、结构
C++ 2 

5、Observer格局的多少个要点

• 
使用面向对象的肤浅,Observer情势使得大家得以独自地改变目的与观看者,从而使二者之间的依靠关系达致松耦合。

• 
目的发送公告时,无需钦点旁观者,公告(能够指点布告新闻作为参数)会活动传播。观望者本人决定是不是要求订阅布告,目的对象对此一无所
知。

• 
在C#的event中,委托充当了画饼充饥的Observer接口,而提供事件的指标担任了对象对象。委托是比抽象Observer接口更为松耦合的设计。

 

⑥ 、项目中央银行使的发布订阅形式的实际例子:(那里其实选取了observer方式的扩充)须要是:当3个目的的情景发生了转变(那里是传播二个音讯给3个指标),那么富有监听这一个指标的别的对象会依据内定的吸收指标的花色调用钦点对象的情势:我们都很领会的问询到observer方式主借使用以当3个目的的图景产生变化的时候,会自动的通告订阅的其余对象,也等于说会把当下的音讯传递给任何对象开展处理。但是有多个题材是,固然其余对象收取到的新闻是由限制的,像某些对象只好收到钦点项目标音信等,那样的话就要求在此前的observer方式上实行补偿:

下边是种类中关于那几个格局的的构造如图:

C++ 3

先是来看看Listener文件夹下的一个文件(其余多少个文件类似)

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

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

  [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文件就是完结这二个作用,代码如下:

C++ 4C++ 5Code
 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;
        }

 

C++ 6C++ 7Code
  /// <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文件来布局节点来贯彻,那样会越来越灵活

C++ 8C++ 9Code
        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. 马丁
* 《重构:改良既有代码的安排》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