移动项目支付笔记,设计情势

下边是一对关于那几个Observer的主导一些概念,在无数地点都能观察,那里自身总结那那里便于今后翻看:

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

① 、发表订阅模型(pub-sub)

发表/订阅简称(Pub/Sub)方式,那种Pub/Sub设计形式是observer的一种变体。Observer格局在Design
patterns用于:1个指标(Observer)观看者被注入到另3个对象(大旨Subject),用于监听事件,观望者(Observer)暗中地呈现(主题Subject)的变化。publish/subscribe方式在大旨(subject)和观看者(observer)之间增添了一层间隔。
这么些层移除了在观察者(observer)和重点(subject)之间的包扎并且在这两时期创建一种松耦合的关联。

爱博体育app下载 1

Pub形式主倘使背负向外发送音讯,Sub首如若订阅音信。首要用于“只承担传递音讯,并不关心其余对象已经收取那一个消息”.

二、动机(Motivation)

上面是运用Pub/Sub那种设计形式场景:

在软件构建进程中,我们需求为一些对象建立一种 “文告依赖关系”
——贰个指标(指标对象)的事态产生变更,全体的借助对象(观看者对象)都将得
到通报。假如那样的借助关系过度紧凑,将使软件不可能很好地抗拒变化。

在实际的业务处理中,往往会有那样的必要:尤其是运用系统需求转移和置换数据,必须传递那些改动的多寡(DomainModel)交给工作逻辑层进行拍卖。特别是多个模块必要那种数据同步协调时,就能够用Pub/Sub那种设计形式来消除难点。

选用面向对象技术,可以将这种信赖关系弱化,并摇身一变一种祥和的依赖关系。从而达成软件类别结构的松耦合。

利益:下跌了应用程序和事务逻辑的耦合,统一的对外Publisher(公布),收缩了依靠。让我们只关怀监听者监听的品种。而不需清楚具体该哪3个类来处理该新闻.上面包车型大巴安顿文件是监听器对象,通过布置显得尤其灵敏。(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是监听指标监听消息的项目。

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

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

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

MonitorFactory.Publisher(new object());

 

处理进程:那些对外公布的Publisher方法被调用的时候,监听者会基于监听的项目自动的通报发出重视的其余对象。那样的客户程序就和事情逻辑完成了松耦合,下跌了客户程序和工作的依靠。客户程序完全不清楚具体调用的是这几个措施,只承担向MonitorFactory发送音信对象(那里是arg参数),监听者就遵照本人承受的新闻自动的打招呼其余相关的指标。

6、项目中央银行使的宣布订阅情势的其实例子:(那里实在接纳了observer形式的扩张)供给是:当一个对象的情景发生了转变(这里是流传二个音讯给1个指标),那么具有监听这一个指标的其余对象会基于钦定的收受指标的品类调用钦定对象的措施:大家都很驾驭的垂询到observer情势首假使用来当2个指标的景况发生变化的时候,会自行的打招呼订阅的别样对象,也便是说会把近来的新闻传递给其余对象举行拍卖。但是有1个难点是,若是其余对象吸收到的音信是由限制的,像有个别对象只好收到钦定项目标音讯等,那样的话就必要在在此以前的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”));
        }

上面是项目中关于那些格局的的组织如图:

        /// <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>
爱博体育app下载,        /// <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. 马丁
* 《重构:改进既有代码的统一筹划》马丁Fowler
* 《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

相关文章