Javascript 基于插件的GUI中的模型视图演示者生命周期管理
当GUI由多个子组件组成时,我将它们视为具有自己的演示者和模型的独立视图,是否有一种将它们粘合在一起的模式?一些子组件会持续出现在屏幕上,而其他子组件则会在屏幕上交换Javascript 基于插件的GUI中的模型视图演示者生命周期管理,javascript,language-agnostic,plugins,mvp,Javascript,Language Agnostic,Plugins,Mvp,当GUI由多个子组件组成时,我将它们视为具有自己的演示者和模型的独立视图,是否有一种将它们粘合在一起的模式?一些子组件会持续出现在屏幕上,而其他子组件则会在屏幕上交换 对于在运行时添加到GUI的子组件,实例化相应的MVP三元组,什么样的工厂模式是好的 如何将子组件与GUI的持久“容器”部分以及彼此粘合在一起?是否会有一个“上帝演讲者”将其他演讲者联系在一起 更新:我现在正在寻找类似Eclipse扩展机制的东西。插件将自己注册到全局注册表,以获得它们提供的功能。当需要返回数据或呈现视图等功能时,将
好的,我现在就停止唠叨,等待一些反馈,然后也许会补充更多关于我到底被困在哪里的澄清…现在,我采用这种方法: 贡献GUI组件的扩展器(插件公开的扩展实现)有一个
getTriad
(稍后将给出更好的名称)方法,该方法实例化、连接并返回MVP三元组。视图有一个getComponent
方法,该方法呈现并返回一个特定于框架的GUI元素容器,该容器可以添加到父容器中(特定于框架的详细信息封装在父视图中)。我不是让视图将自身渲染到容器中,而是让父视图将子视图渲染到自身中。我认为这在确保子视图不会直接干扰父视图方面更好。我想“保持特定于GUI框架的内部视图实现”是整个应用程序级设计的选择,而不是绝对必须的(至少当您认为“视图实现”是“插件视图实现”时)
例如,您可以在插件级别有一个非常薄的视图层,并在父级中实现一个调用插件的超级视图层:考虑到一个插件系统,所有插件都向表中添加了一列,您很可能在父级(“表”)拥有大部分视图代码让你的插件只传递一点点原始数据:你将避免重复自己的工作,并使你的代码更加灵活和可维护
另一方面,如果您的插件提供了非常不同类型的功能,而这些功能从未直接交互(例如,如果它们是飞行模拟器的不同子系统),那么您将希望将所有与视图相关的内容都保留在插件级别,以便父对象甚至不必知道给定插件所处理的内容,但只需将其返回值放在GUI中的某个位置即可
其他可能影响您选择的因素是您正在使用的语言和框架(如果有):根据我个人的经验,设计模式与语言无关,因为每种语言(和框架)有自己的优势/劣势,使得某些选择显而易见,而某些选择很难实施
不管怎么说,只有我的2美分参加讨论!:) 我认为您讨论的设计模式是mediator 我已经编写了一个javascript框架,其中包含一个中介 它的工作原理如下:
- 您将创建 调解人
- 将对象注册到 某些名字
- 在实现中使用中介来调用方法 来自以下任何一个域中的注册对象: 物体
@大卫·默多克。谢谢编辑大卫。大写字母用于指代在我居住的地方有“你”的人。仅供参考:你不应该仅仅因为某件事让你烦恼而编辑别人的答案[按要求写一封小信]。有人可能会生气。
function Mediator(){
function log(a){
try {console.log(a);} catch(e){
try {opera.postError(a);} catch(e){
//alert(a);
}
}
}
var __reg={}; // { "what": [object, ...], ... } //registers an object
//what=key that will identify, obj=an object
this._register = function(what,obj){
if(__reg[what]===undefined){
__reg[what]=[];
}
__reg[what].push(obj);
} //unregisters multiple objects and deletes a key
this._unregisterAll = function(what){
if(__reg[what]===undefined){log('Overlord:_unregisterAll - no registers'); return false; }
__reg[what]=null;
return true;
}
//unregisters a single element key
this._unregister = function(what){
if(this._countRegisters()==1){
__reg[what]=null;
return true;
} else { log('Overlord:_unregister - no registers'); return false; }
}
//unregisters last added element
this._unregisterLast = function(what){
var cnt=this._countRegisters(what);
if(cnt==0) { log('Overlord:_unregisterLast - no registers'); return false; }
if(cnt==1) {
__reg[what]=null;
return true;
} else {
__reg[what][cnt-1]=null;
return true;
}
}
//returns number of registered items
this._countRegisters = function(what){
try{
return __reg[what].length;
} catch(e){log(e);
return 0;
}
} //calls a method from all objects registered under 'what' with an array of parameters. returns true if there was at least one successful call
this._call = function(what,method,params){
var occured=false;
for(var i in __reg[what]) {
try {
__reg[what][i][method](params);
occured=true;
} catch(e) {log(e);//auto reakcja
}
}
return occured;
}
//does the call, but also returns an array of values retuurned by function
this._returnAll = function(what,method,params){
var re=[];
for(var i in __reg[what]){
try {
re.push(__reg[what][i][method](params));
} catch(e) {log(e);//auto reakcja
}
}
return re;
}
//runs a method from first object for a given key
this._returnFirst = function(what,method,params){
try {
return __reg[what][0][method](params);
} catch(e) {log(e);//auto reakcja
return null;
}
}
}