学习资料:pureMv中文指南,C++ puremvc代码
根据图示,顺着信息流动的途径,应该从facede入手,接着controller,控制command,command操控proxy与mediation,形成一个信息闭环。书籍参考指南的顺序很难给读者一个清晰的框架认识,个人如此认为。指南从基础的view,model,controller等基础开始,并没有从整体勾勒。个人认为应该先从整体大概把握整体架构,比如:主体循环如何执行,如何将三个核心部分组合,如何将组件结合,顺着线索,步步深入代码如何执行。
一、PureMvc结构
在PureMVC实现的经典MVC元设计模式中,这三部分由三个单例模式类管理,分别是Model、View和Controller。PureMVC中还有另外一个单例模式类——Façade,Façade提供了与核心层通信的唯一接口。
进入代码:
1.Facade代码
遇到explicit
http://www.cnblogs.com/cutepig/archive/2009/01/14/1375917.html
facade为单例模式
<span style="font-family:Microsoft YaHei;font-size:10px;"> public:
/**
* Facade Multiton Factory method
*
* @return the Multiton instance of the Facade
*/
static IFacade& getInstance(std::string const& key = Facade::DEFAULT_KEY);
</span>
在facade代码中初始化等函数都放入project进行保护,习惯很好,注意学习。
对Core中的三个核心部分保持引用
<span style="font-family:Microsoft YaHei;font-size:10px;"> protected:
// References to Model, View and Controller
IController* _controller;
IModel* _model;
IView* _view;
// Message Constants
static char const* const MULTITON_MSG;
</span>
使用的是面对接口编程。
代码中基本定义的是后面子类需要定义的函数,后面使用的时候,用的是“I”文件代码,具体的实现的类调用的是虚函数,虚函数在具体类中实现,这样就进行了解耦。
2.model代码
其中再次遇到multiton多例模式,http://blog.csdn.net/hsyj_0001/article/details/648033。
类似于facade同样采用的是多例模式的做法。
<span style="font-family:Microsoft YaHei;font-size:10px;">IModel& Model::getInstance(std::string const& key)
{
IModel* result = puremvc_model_instance_map.find(key) ;
if (result == NULL)
{
result = new Model(key);
puremvc_model_instance_map.insert(std::make_pair(key, result));
}
return *result;
}
</span>
同时保留对proxy的引用
<span style="font-family:Microsoft YaHei;font-size:10px;"> // Mapping of proxyNames to IProxy instances
ProxyMap _proxy_map;</span>
Proxy负责操作数据模型,与远程服务通信存取数据。具体作用细则还需看源代码。3.View代码
<span style="font-family:Microsoft YaHei;font-size:10px;"> typedef std::tr1::unordered_map<std::string, IMediator*> MediatorMap;
typedef std::tr1::unordered_multimap<std::string, IObserver*> ObserverMap;
</span>
View保存对Mediator对象的引用。
在注册mediation中,调用代码
while(iter->moveNext())
{
// Register Mediator as Observer for its list of Notification interests
// Create Observer referencing this mediator's handlNotification method
IObserver *observer = createObserver(&IMediator::handleNotification, mediator);
puremvc_observer_instance_map.insert(observer);
registerObserver(iter->getCurrent(), observer);
}
同时也会在mediation_map中进行注册。
需要仔细阅读view registerobserved函数,其中observ注册函数采用多维map。
4.control代码
基本类型与模式都与其他核心模块一样,核心模块部分都采取一样的架构。
总结下,保持的引用的用处不明,虽有说明,但是脉络依旧不清晰。
5.Observer 与 Notification
采用的是观察者模式,观察者模式的定义是:有时被称作发布/订阅模式,观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
http://www.cnblogs.com/wangjq/archive/2012/07/12/2587966.html
6.Mediation
protected:
// the mediator name
std::string _mediator_name;
// The view component
void const* _view_component;
public:
static char const* const NAME;
保留了view的引用。
继承于
: public virtual IMediator
, public virtual INotifier
, public Notifier
7.转化View Component类型
跟随源代码可以看到,从mediator存入的component组件都是void指针形式,可以自主定义方法get,使用类型转换获取正确的类型,方便获取。
8.Proxy
Proxy从本质上来说是Model对外的接口,与外界操作剥离,实现数据部分独立。所有的proxy都存储在model中的map中,方便facade自由存取,facade获取proxy之后就能很方便的使用proxy提供的方法进行操作了。下面我还会在消息机制中提供一张图,里面有proxy存取的路径,可以参考一下。每个proxy可以设置一个void指针,用来专门存储数据指针,setdata或者在构造函数中添加。Proxy管理的是域逻辑操作,比如说游戏中球的位置,速度,加速度变化,与其他物体碰撞等等域逻辑都应该放在proxy中,属于域模型中的规则体现。
8.关于消息机制
这里快接近尾声了,总结一下学习这个框架的经验,其实直接看书的效率不高,最适合的方法是结合源代码边看书边看代码实现,成效居高,基本一遍过大概,两遍开始通,三四遍后。。。。。
PureMVC文档到后面部分主要就是消息机制的内容,跟随代码,注册与通知大体结构.
二、代码解释
1.Pattern
Observer:
Notification 消息,相当于信封中存放的信,包含需要传输的信息。
class Notification : public INotification
{
public:
/**
* 构造函数
*
* @param name name of the <code>Notification</code> instance. (required)
* @param body the <code>Notification</code> body. (optional)
* @param type the type of the <code>Notification</code> (optional)
*/
explicit Notification(Notification const& arg);
Notification(std::string const& name, void const* body = NULL, std::string const& type = "");
/**
* 获取notifacation的名字,在每次生成时都有对应的名字。
*
* @return the name of the <code>Notification</code> instance.
*/
virtual std::string getName() const;
/**
* 获取notification上所绑定的void指针,用于传递任意对象。
*/
virtual void setBody( void* body );
/**
* Get the body of the <code>Notification</code> instance.
*
* @return the body object.
*/
virtual void* getBody();
/**
* Set the type of the <code>Notification</code> instance.
*/
virtual void setType( const std::string & type);
/**
* Get the type of the <code>Notification</code> instance.
*
* @return the type
*/
virtual std::string getType();
/**
* Get the string representation of the <code>Notification</code> instance.
*
* @return the string representation of the <code>Notification</code> instance.
*/
virtual std::string toString() const;
Notification& operator=(Notification const &arg);
virtual ~Notification();
private:
// the name of the notification instance
std::string m_name;
// the type of the notification instance
std::string m_type;
// the body of the notification instance
void* m_body;
};
class Notifier : public virtual INotifier
{
/**
* 创造并且发送Notification 消息
*
* <P>
* Keeps us from having to construct new INotification
* instances in our implementation code.
* @param notificationName the name of the notiification to send
* @param body the body of the notification (optional)
* @param type the type of the notification (optional)
*/
public:
explicit Notifier();
virtual ~Notifier();
<span style="white-space:pre"> </span>// 创造并发送消息
virtual void sendNotification(std::string const& notification_name, void const* body = NULL, std::string const& type = "");
// virtual void sendNotificationTo(const INotification& ,ObserverMediators&)
// {
//
// }
virtual void initializeNotifier(std::string const& key);
virtual std::string const& getMultitonKey(void) const;
Notifier& operator=(Notifier const& arg);
// Local reference to the Facade Singleton
protected:
IFacade& getFacade();
IFacade * m_facade ;
std::string _multiton_key;
};
Observer 观察者 用于接收消息,当消息被发送之后,就去遍历观察者数组。其中存储了关注的消息被触发后需要执行的函数,执行函数的主体,内容。
template<typename _Method ,typename _Context>
class Observer : public IObserver
{
/**
* Constructor.
*
* <P>
* The notification method on the interested object should take
* one parameter of type <code>INotification</code></P>
*
* @param notifyMethod the notification method of the interested object
* @param notifyContext the notification context of the interested object
*/
public:
<span style="white-space:pre"> </span>explicit Observer(Observer const &atg)
<span style="white-space:pre"> </span>:IObserver()
<span style="white-space:pre"> </span>,_notify_method(arg._notify_method)
<span style="white-space:pre"> </span>,_notify_context(arg._notify_context)
<span style="white-space:pre"> </span>{}
<span style="white-space:pre"> </span>explicit Observer(_Method notify_method, _Context* notify_context)
<span style="white-space:pre"> </span>: IObserver()
<span style="white-space:pre"> </span>, _notify_method(notify_method)
<span style="white-space:pre"> </span>, _notify_context(notify_context)
<span style="white-space:pre"> </span>{ }
virtual ~Observer(){}
/**
* Set the notification method.
*
* <P>
* The notification method should take one parameter of type <code>INotification</code>.</P>
*
* @param notifyMethod the notification (callback) method of the interested object.
*/
<span style="white-space:pre"> </span>virtual void notifyObserver(INotification const& notification)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>if (_notify_context == NULL)
<span style="white-space:pre"> </span>throw std::runtime_error("Notify context is null.");
<span style="white-space:pre"> </span>if (_notify_method == NULL)
<span style="white-space:pre"> </span>throw std::runtime_error("Notify method is null.");
<span style="white-space:pre"> </span>(*_notify_context.*_notify_method)(notification);
<span style="white-space:pre"> </span>}
/**
* Set the notification context.
*
* @param notifyContext the notification context (this) of the interested object.
*/
<span style="white-space:pre"> </span>virtual bool compareNotifyContext(void const* object) const
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>return _notify_context == object;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>Observer& operator=(Observer const& arg)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>_notify_method = arg._notify_method;
<span style="white-space:pre"> </span>_notify_context = arg._notify_context;
<span style="white-space:pre"> </span>return *this;
<span style="white-space:pre"> </span>}
private :
<span style="white-space:pre"> </span>_Method _notify_method;
<span style="white-space:pre"> </span>_Context* _notify_context;
};
/**
* Create new observer.
*/
template<typename _Method, typename _Context>
inline IObserver* createObserver(_Method notify_method, _Context* notify_context)
{
return new Observer<_Method, _Context>(notify_method, notify_context);
}
/**
* Make an observer.
*/
template<typename _Method, typename _Context>
inline Observer<_Method, _Context> makeObserver(_Method notify_method, _Context* notify_context)
{
return Observer<_Method, _Context>(notify_method, notify_context);
}
Command:
simpleCommand 简单的命令,其中只存储了命令被触发时需要执行的函数execute。
class SimpleCommand :public virtual INotifier,public virtual ICommand ,public Notifier
{
public:
/**
* Fulfill the use-case initiated by the given <code>INotification</code>.
*
* <P>
* In the Command Pattern, an application use-case typically
* begins with some user action, which results in an <code>INotification</code> being broadcast, which
* is handled by business logic in the <code>execute</code> method of an
* <code>ICommand</code>.</P>
*
* @param notification the <code>INotification</code> to handle.
*/
virtual void execute( const INotification & notification);
virtual ~SimpleCommand(){}
};
macrocommand :一种比较复杂的命令,可以存储一系列简单的命令,macrocommand被触发后,依次执行所存储的simplecommand。
// 添加simplecommand到数组列表中
virtual void addSubCommand( ICommand *pCmd );
/**
* Execute this <code>MacroCommand</code>'s <i>SubCommands</i>.
*
* <P>
* The <i>SubCommands</i> will be called in First In/First Out (FIFO)
* order.
*
* @param notification the <code>INotification</code> object to be passsed to each <i>SubCommand</i>.
*/
// 依次执行数组中的simplecommand
virtual void execute(INotification const& notification);
class Mediator : public virtual IMediator ,public virtual INotifier ,public Notifier
{
public:
/**
* Constructor.
*/
explicit Mediator(Mediator const& arg);
Mediator(const std::string & mediatorName="", void * viewComponent=NULL );
virtual ~Mediator();
/**
*每个mediator都有各自的名字
* @return the Mediator name
*/
virtual std::string getName();
/**
* Set the <code>IMediator</code>'s view component.
*
* @param Object the view component
*/
void setViewComponent( void * viewComponent );
/**
* 设置mediator组件
*
*
* @return the view component
*/
void * getViewComponent();
/**
* 返回Mediator所关心的信息
* <code>Mediator</code> is interested in being notified of.
*
* @return Array the list of <code>INotification</code> names
*/
Interests listNotificationInterests();
/**
* 当所关心的信息被触发时 执行的函数。
*
*/
virtual void handleNotification( const INotification & notification) ;
/**
* 当被注册的时候,调用
*/
virtual void onRegister( );
/**
* 当被移除的时候调用
*/
virtual void onRemove( );
Mediator& operator=(Mediator const& arg);
// the mediator name
protected:
std::string m_mediatorName;
// The view component
void * m_viewComponent;
};