关于pureMVC框架的笔记

这两天学习 骏擎【CP】大神的uLua,看到里面pureMVC框架的时候发现逻辑有点绕,于是将其扒下来作一个单独处理。


从设计模式角度看,pureMVC是一个集命令模式、代理模式、外观模式、中介模式、观察者模式、单例模式的杂交品种,自然pureMVC也就集成了这些模式的一些设计上的优势(但感觉还是太绕)。pureMVC大框架还是保持着传统的MVC框架,只是在传统MVC结构的基础上,作了进一步的解耦。下面简单捋一捋框架。


1)框架的组成

Facade:单例。整个框架的对外的接口,也是消息传递的出入口。仅仅是Controller,Model,View三个单例对外的控制面板(外观)。

Controller:单例。命令管理器,负责命令的注册/注销和执行。维护了一张Command表,每一条消息对应一条命令,以消息名区分命令,一条命令可由多条子命令组成。

Model:单例。数据管理器,负责数据获取与包装。维护了一张IProxy表,每个IProxy处理一个模型的数据。

View:单例。消息监听器,负责在接收到消息后通知相应的Observer作出消息响应,维护了一张IMediator表和一张IObserver表。当然,在接收消息之前View应该已经将接收该消息的Observer和处理该消息的Mediator注册到表中了,所以,Mediator和Observer是捆绑在一起注册进view中的,Observer负责接收,并不自己处理,但Observer知道如何处理(即知道调用Mediator里哪个函数名),于是,在接收到消息时,由 Observer接收消息,并通知Mediator执行消息处理函数。

Observer:消息监听器。当view NotifyObservers时,会判断该Observer是否已经订阅了该消息,如果订阅了,则会通知该Observer,该Observer会找到相应的Context作出回应。

Notification:消息对象,用于传递一些消息数据。

Mediator:中介。View和UI之间的中间层,与UI对象绑定,负责UI对象的消息处理和发送,是实际上的UI控制器。

Proxy:数据代理。

Command:命令对象。


2)框架的运作

虽然框架里面很绕,也遭很多人吐槽,但框架外面,也确实是干干净净,仿佛在狭小的山洞里爬了一整天刚走到出口的感觉。

应用层面上,最简单我们只需要做3件事:构造命令-》注册命令-》发送命令。如:

public class CloseCommand : ICommand {
        public void Execute(INotification notification) { 
            Console.WriteLine("excete CloseCommand..");
        }
    }
Facade.Instance.RegisterCommand(NotiConst.CLOSE, typeof(CloseCommand));
Facade.Instance.SendNotification(NotiConst.CLOSE);


3)框架Demo

/* 
* created by panyinglong at 2015-8-14
*/
using System;
using System.Collections.Generic;
using System.Reflection;

namespace PureMVC {
    //------------------ framework -----------------------
    #region message
    class Observer : IObserver{
		public Observer(string notifyMethod, object notifyContext){
			m_notifyMethod = notifyMethod;
			m_notifyContext = notifyContext;
		}
		public virtual void NotifyObserver(INotification notification){
			object context;
			string method;

			lock (m_syncRoot){
				context = NotifyContext;
				method = NotifyMethod;
			}

			Type t = context.GetType();
			BindingFlags f = BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase;
			MethodInfo mi = t.GetMethod(method, f);
			mi.Invoke(context, new object[] { notification });
		}
		public virtual bool CompareNotifyContext(object obj){
			lock (m_syncRoot){
				return NotifyContext.Equals(obj);
			}
		}
		public virtual string NotifyMethod{
			private get{
				return m_notifyMethod;
			}set{
				m_notifyMethod = value;
			}
		}
		public virtual object NotifyContext{
			private get{
				return m_notifyContext;
			}set{
				m_notifyContext = value;
			}
		}
		private string m_notifyMethod;
		private object m_notifyContext;
		protected readonly object m_syncRoot = new object();
	}
    class Notification : INotification{
		private string m_name;
		private string m_type;
		private object m_body;

        public Notification(string name) : this(name, null, null){ 
        }

        public Notification(string name, object body) : this(name, body, null){ 
        }

        public Notification(string name, object body, string type){
			m_name = name;
			m_body = body;
			m_type = type;
		}

		public virtual string Name{
			get { return m_name; }
		}
		
		public virtual object Body{
			get{
				return m_body;
			}set{
				m_body = value;
			}
		}
		
		public virtual string Type{
			get{
				return m_type;
			}set{
				m_type = value;
			}
		}
	}
    #endregion

    // mediator
    public class Mediator : IMediator, INotifier{
		public const string NAME = "Mediator";
        protected string m_mediatorName;
        protected object m_viewComponent;

        public Mediator()
            : this(NAME, null){
        }
        public Mediator(string mediatorName)
            : this(mediatorName, null){
		}
		public Mediator(string mediatorName, object viewComponent){
			m_mediatorName = (mediatorName != null) ? mediatorName : NAME;
			m_viewComponent = viewComponent;
		}
		public virtual string MediatorName{
			get { return m_mediatorName; }
		}
		public virtual object ViewComponent{
			get { return m_viewComponent; }
			set { m_viewComponent = value; }
		}
        public virtual void SendNotification(string notificationName) {
			Facade.Instance.SendNotification(notificationName);
		}

		public virtual void SendNotification(string notificationName, object body){
			Facade.Instance.SendNotification(notificationName, body);
		}

		public virtual void SendNotification(string notificationName, object body, string type){
            Facade.Instance.SendNotification(notificationName, body, type);
		}
		public virtual IList<string> ListNotificationInterests(){
			return new List<string>();
		}
		public virtual void HandleNotification(INotification notification){
		}
		public virtual void OnRegister(){
		}
		public virtual void OnRemove(){
		}
	}

    #region interface
    public interface INotification
    {
		string Name { get; }
		object Body { get; set; }
        string Type { get; set; }
    }
    public interface ICommand
    {
		void Execute(INotification notification);
    }
    public interface IObserver
    {
		string NotifyMethod { set; }
		object NotifyContext { set; }
        void NotifyObserver(INotification notification);
		bool CompareNotifyContext(object obj);
    }
    public interface IProxy
    {
		string ProxyName { get; }
		object Data { get; set; }
		void OnRegister();
		void OnRemove();
    }
    public interface IMediator
	{
		string MediatorName { get; }
		object ViewComponent { get; set; }
        IList<string> ListNotificationInterests();
		void HandleNotification(INotification notification);
		void OnRegister();
		void OnRemove();
	}
    public interface INotifier
    {
		void SendNotification(string notificationName);
		void SendNotification(string notificationName, object body);
		void SendNotification(string notificationName, object body, string type);
    }
    public interface IController
    {
        void RegisterCommand(string notificationName, Type commandType);
		void ExecuteCommand(INotification notification);
		void RemoveCommand(string notificationName);
		//bool HasCommand(string notificationName);
	}
    public interface IFacade : INotifier
	{
		void RegisterProxy(IProxy proxy);
		IProxy RetrieveProxy(string proxyName);
        IProxy RemoveProxy(string proxyName);
		//bool HasProxy(string proxyName);
        void RegisterCommand(string notificationName, Type commandType);
		void RemoveCommand(string notificationName);
		//bool HasCommand(string notificationName);
		void RegisterMediator(IMediator mediator);
		IMediator RetrieveMediator(string mediatorName);
        IMediator RemoveMediator(string mediatorName);
		//bool HasMediator(string mediatorName);
		//void NotifyObservers(INotification note);
	}
    public interface IModel
    {
		void RegisterProxy(IProxy proxy);
		IProxy RetrieveProxy(string proxyName);
        IProxy RemoveProxy(string proxyName);
		//bool HasProxy(string proxyName);
    }
    public interface IView
	{
		void RegisterObserver(string notificationName, IObserver observer);
		void RemoveObserver(string notificationName, object notifyContext);
		void NotifyObservers(INotification note);
		void RegisterMediator(IMediator mediator);
		IMediator RetrieveMediator(string mediatorName);
        IMediator RemoveMediator(string mediatorName);
		//bool HasMediator(string mediatorName);
	}
    #endregion
    
    #region M/V/C sigleton
    public class Controller : IController {
        private static Controller _instance;
        private Dictionary<string, Type> m_commandMap;
        private static readonly object m_syncRoot = new object();

        private Controller() {            
			m_commandMap = new Dictionary<string, Type>();	
        }
        public static Controller Intance{
            get{
                if (_instance == null) {
                    _instance = new Controller();
                }
                return _instance;
            }
        }
        public void RegisterCommand(string notificationName, Type commandType) { 
            lock (m_syncRoot){
                if (!m_commandMap.ContainsKey(notificationName)){   // 监听SendNotification(notificationName),监听到则执行this.executeCommand
				    View.Instance.RegisterObserver(notificationName, new Observer("executeCommand", this));
			    }
				m_commandMap[notificationName] = commandType;
			}
        }
		public void RemoveCommand(string notificationName){
            lock (m_syncRoot){
				if (m_commandMap.ContainsKey(notificationName)){
					m_commandMap.Remove(notificationName);
				}
			}
        }
        public void ExecuteCommand(INotification notification) {
            Type commandType = null;

			lock (m_syncRoot){
				if (!m_commandMap.ContainsKey(notification.Name)) 
                    return;
				commandType = m_commandMap[notification.Name];
			}
            object commandInstance = Activator.CreateInstance(commandType); // 反射创建对象
			if (commandInstance is ICommand){
				((ICommand) commandInstance).Execute(notification);
			}
        }
    }   
    public class View : IView {
		private IDictionary<string, IMediator> m_mediatorMap;
		private IDictionary<string, IList<IObserver>> m_observerMap;
		private static View _instance;
		protected readonly object m_syncRoot = new object();
		protected static readonly object m_staticSyncRoot = new object();

		private View(){
			m_mediatorMap = new Dictionary<string, IMediator>();
			m_observerMap = new Dictionary<string, IList<IObserver>>();
		}
        public static View Instance{
            get{
                if (_instance == null) {
                    _instance = new View();
                }
                return _instance;
            }
        }
		public virtual void RegisterObserver(string notificationName, IObserver observer){
			lock (m_syncRoot){
				if (!m_observerMap.ContainsKey(notificationName)){
					m_observerMap[notificationName] = new List<IObserver>();
				}
				m_observerMap[notificationName].Add(observer);
			}
		}
		public virtual void NotifyObservers(INotification notification){
			IList<IObserver> observers = null;
			lock (m_syncRoot){
				if (m_observerMap.ContainsKey(notification.Name)){
					IList<IObserver> observers_ref = m_observerMap[notification.Name];
					observers = new List<IObserver>(observers_ref);
				}
			}
			if (observers != null){	
				for (int i = 0; i < observers.Count; i++){
					IObserver observer = observers[i];
					observer.NotifyObserver(notification);
				}
			}
		}
		public virtual void RemoveObserver(string notificationName, object notifyContext){
			lock (m_syncRoot){
				if (m_observerMap.ContainsKey(notificationName)){
					IList<IObserver> observers = m_observerMap[notificationName];
					for (int i = 0; i < observers.Count; i++){
						if (observers[i].CompareNotifyContext(notifyContext)){
							observers.RemoveAt(i);
							break;
						}
					}
					if (observers.Count == 0){
						m_observerMap.Remove(notificationName);
					}
				}
			}
		}
		public virtual void RegisterMediator(IMediator mediator){
			lock (m_syncRoot){
				if (m_mediatorMap.ContainsKey(mediator.MediatorName)) 
                    return;

				m_mediatorMap[mediator.MediatorName] = mediator;

				IList<string> interests = mediator.ListNotificationInterests();
				if (interests.Count > 0){
					IObserver observer = new Observer("handleNotification", mediator);  // 由mediator接收消息并做出回应
					for (int i = 0; i < interests.Count; i++){
						RegisterObserver(interests[i].ToString(), observer);
					}
				}
			}
			mediator.OnRegister();
		}
		public virtual IMediator RetrieveMediator(string mediatorName){
			lock (m_syncRoot){
				if (!m_mediatorMap.ContainsKey(mediatorName)) return null;
				return m_mediatorMap[mediatorName];
			}
		}
		public virtual IMediator RemoveMediator(string mediatorName){
			IMediator mediator = null;

			lock (m_syncRoot){
				if (!m_mediatorMap.ContainsKey(mediatorName)) return null;
				mediator = (IMediator) m_mediatorMap[mediatorName];

				IList<string> interests = mediator.ListNotificationInterests();
				for (int i = 0; i < interests.Count; i++){
					RemoveObserver(interests[i], mediator);
				}
				m_mediatorMap.Remove(mediatorName);
			}
			if (mediator != null) mediator.OnRemove();
			return mediator;
		}
    }
    public class Model : IModel 
    {
		protected IDictionary<string, IProxy> m_proxyMap;
		protected static Model _instance;
		protected readonly object m_syncRoot = new object();
		protected static readonly object m_staticSyncRoot = new object();
		private Model(){
			m_proxyMap = new Dictionary<string, IProxy>();
		}
        public static Model Instance{
			get{
				if (_instance == null){
					_instance = new Model();
				}
				return _instance;
			}
		}
		public virtual void RegisterProxy(IProxy proxy){
			lock (m_syncRoot){
				m_proxyMap[proxy.ProxyName] = proxy;
			}

			proxy.OnRegister();
		}
		public virtual IProxy RetrieveProxy(string proxyName){
			lock (m_syncRoot){
				if (!m_proxyMap.ContainsKey(proxyName)) return null;
				return m_proxyMap[proxyName];
			}
		}
		public virtual IProxy RemoveProxy(string proxyName){
			IProxy proxy = null;
			lock (m_syncRoot){
				if (m_proxyMap.ContainsKey(proxyName)){
					proxy = RetrieveProxy(proxyName);
					m_proxyMap.Remove(proxyName);
				}
			}
			if (proxy != null) proxy.OnRemove();
			return proxy;
		}
    }
    public class Facade : IFacade 
    {
        private static Facade _instance;

        private Facade(){}

        public static Facade Instance{
            get{
                if (_instance == null) {
                    _instance = new Facade();
                }
                return _instance;
            }
        }
        public void RegisterCommand(string notificationName, Type commandType){
            Controller.Intance.RegisterCommand(notificationName, commandType);
        }
        public virtual void RemoveCommand(string notificationName){
			Controller.Intance.RemoveCommand(notificationName);
		}


        public void RegisterProxy(IProxy proxy){
			Model.Instance.RegisterProxy(proxy);
		}
        public virtual IProxy RetrieveProxy(string proxyName){
			return Model.Instance.RetrieveProxy(proxyName);
		}
        public IProxy RemoveProxy(string proxyName){
			return Model.Instance.RemoveProxy(proxyName);
		}

        public void RegisterMediator(IMediator mediator){
			View.Instance.RegisterMediator(mediator);
		}
        public virtual IMediator RetrieveMediator(string mediatorName){
			return View.Instance.RetrieveMediator(mediatorName);
		}
        public virtual IMediator RemoveMediator(string mediatorName){
			return View.Instance.RemoveMediator(mediatorName);
		}

        public void SendNotification(string notificationName){
			View.Instance.NotifyObservers(new Notification(notificationName));
		}
        public void SendNotification(string notificationName, object body){
			View.Instance.NotifyObservers(new Notification(notificationName, body));
		}
        public void SendNotification(string notificationName, object body, string type){
			View.Instance.NotifyObservers(new Notification(notificationName, body, type));
		}
    }
    #endregion
    //---------------------------- end ------------------------------
}

namespace PureMVCDemoSimplify {
    using PureMVC;

    class test {
        static void Main()
        {
            ProgramManager pro = new ProgramManager();
            pro.StartUp();
   
            Console.Read();
        }
    }
    
    #region logic

    public class NotiConst{
        public const string START_UP = "StartUp";                       //启动框架
        public const string LOAD_UI = "LoadUI";                         //初始化UI
        public const string LOGIN = "Login";                            //登录
        public const string CLOSE = "Close";                            //关闭UI
    }

    public class myView {
        public myView() { 
        }
        public void ShowUI() {            
            Console.WriteLine("welcome to pureMVC demo. print 'L' to login; other to close.");
            ConsoleKeyInfo c = Console.ReadKey();
            Console.WriteLine();
            if (c.KeyChar == 'L' || c.KeyChar == 'l') {
                Facade.Instance.SendNotification(NotiConst.LOGIN);
                Facade.Instance.RemoveCommand(NotiConst.LOGIN);
            } else {
                Facade.Instance.SendNotification(NotiConst.CLOSE);
                Facade.Instance.RemoveCommand(NotiConst.CLOSE);
            }
        }
        public void OnLogin(INotification notification) { 
            Console.WriteLine("login succeed!");
        }
        public void OnClose(INotification notification) {  
            Console.WriteLine("closed!");
        }
    }
    public class myMediator : Mediator {
        public const string NAME = "myMediator";
        public myMediator(object viewComponent) : base(NAME, viewComponent) {
        }
        public myView view {
            get {
                return ViewComponent as myView;
            }
        }
        // AppMediator需要监听的消息
        override public IList<string> ListNotificationInterests() {
            return new List<string>()
            { 
                NotiConst.LOGIN,
                NotiConst.CLOSE
            };
        }
        override public void HandleNotification(INotification notification) {
            string name = notification.Name;
            switch (name) {
                case NotiConst.LOGIN:      //登录
                    view.OnLogin(notification);
                break;
                case NotiConst.CLOSE:      //关闭
                    view.OnClose(notification);
                break;
            }
        }
    }

    public class StartUpCommand : ICommand {
        public void Execute(INotification notification) {
            Console.WriteLine("excete StartUpCommand..");
            Facade.Instance.SendNotification(NotiConst.LOAD_UI);
            Facade.Instance.RemoveCommand(NotiConst.LOAD_UI);
        }
    }
    public class LoadUICommand : ICommand {
        public void Execute(INotification notification) {  
            Console.WriteLine("excete LoadUICommand..");                    
            myView view = new myView();
            Facade.Instance.RegisterMediator(new myMediator(view));
            view.ShowUI();
        }
    }
    public class LoginCommand : ICommand {
        public void Execute(INotification notification) { 
            Console.WriteLine("excete LoginCommand..");
        }
    }
    public class CloseCommand : ICommand {
        public void Execute(INotification notification) { 
            Console.WriteLine("excete CloseCommand..");
        }
    }
    public class ProgramManager {
        public void StartUp() { 
            Facade.Instance.RegisterCommand(NotiConst.START_UP, typeof(StartUpCommand));
            Facade.Instance.RegisterCommand(NotiConst.LOAD_UI, typeof(LoadUICommand));
            Facade.Instance.RegisterCommand(NotiConst.LOGIN, typeof(LoginCommand));
            Facade.Instance.RegisterCommand(NotiConst.CLOSE, typeof(CloseCommand));

            Facade.Instance.SendNotification(NotiConst.START_UP);
            Facade.Instance.RemoveCommand(NotiConst.START_UP);
        }
    }
    
    #endregion

}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值