2010-08-17 5 views
2

GUI가 개별 Presenter 및 Models를 개별 뷰로 취급하는 여러 하위 구성 요소로 구성되는 경우 GUI를 함께 붙일 패턴이 있습니까? 일부 하위 구성 요소는 지속적으로 화면에 나타나고 다른 구성 요소는 스왑 아웃 및 스왑 아웃됩니다.플러그인 기반 GUI에서 Model-View-Presenter 라이프 사이클 관리

  1. 런타임에 GUI에 추가되는 하위 구성 요소에 대해 각각의 MVP 트라이어드를 인스턴스화하는 좋은 공장 패턴은 무엇입니까?
  2. GUI의 영구 "컨테이너"부분과 하위 구성 요소를 어떻게 접착합니까? 다른 발표자들을 하나로 묶어주는 "신 발표자"가 있을까요?

업데이트 : 이제 Eclipse의 확장 메커니즘과 유사한 것으로 촬영하고 있습니다. 플러그인은 자신이 제공하는 기능에 대한 전역 레지스트리에 자신을 등록합니다. 데이터를 반환하거나 뷰 렌더링과 같은 기능이 필요할 때 레지스트리를 쿼리하고 반환 된 함수를 호출합니다 (이것은 순수한 JavaScript이므로 인터페이스를 사용하지 않습니다). 필자는 모든 것이 (메인보기조차도) 플러그인인 순수한 플러그인 방식으로 갈 것입니다. 또한 이벤트 버스를 사용하여 다양한 발표자가 알맹이없이 의사 소통 할 수 있도록 할 수 있습니다.

이제 플러그인이 View에 기여하려고 할 때 MVP 트라이어드를 초기화하고 뷰를 부모 컨테이너 (모듈 외부)로 렌더링하는 방법에 대해 좀 더 구체적으로 질문 할 것입니다. 아마 외부에서 전달 된 컨테이너에 View 자체를 렌더링하고 View and Model (필요한 경우)을 Presenter에 주입해야합니다. 또 다른 방법은 View가 컨테이너 내부에 배치 할 수있는 구성 요소를 반환하는 것이지만, 이는 GUI 프레임 워크 관련 View 구현 내부의 모든 것을 유지하는 나의 임시적인 반대가 아닐 수 있습니다. 나는 공장/접착제 메커니즘이 프레임 워크에 독립적 일 수 있다면 더 선호한다.

OK 나는

지금은

답변

1

"GUI 프레임 워크 고유의 내부 뷰 구현을 유지하는 것"은 절대적인 것보다는 (최소한 "구현보기"를 "플러그인보기"로 생각할 때) 전체적인 응용 프로그램 수준 디자인 선택입니다 이행").

예를 들어, 플러그인 수준에서 매우 얇은보기 레이어를 가질 수 있으며 상위에 플러그인을 호출하는 수퍼 뷰 레이어를 구현할 수 있습니다. 즉, 모든 열을 테이블에 추가하는 플러그인 시스템을 생각하면, 상위 수준 ("표")의 뷰 코드를 대량으로 가질 수 있으며 원시 데이터보다 약간만 전달하는 플러그인을 가질 수 있습니다. 반복하지 않아도되고 코드를보다 유연하고 유지 관리 할 수 ​​있습니다.

반면에 플러그인이 직접 상호 작용하지 않는 매우 다른 유형의 기능을 제공하는 경우 (예 : 비행 시뮬레이터의 다른 하위 시스템 인 경우) 플러그인 수준에서보기와 관련된 모든 것을 유지하고자 할 것입니다 따라서 부모 객체는 주어진 플러그인이 처리하는 것을 알 필요가 없지만 GUI의 어딘가에 반환 값을 배치합니다.

당신이 사용하는 언어와 프레임 워크가 있다면 그 선택에 영향을 줄 수있는 다른 요소는 다음과 같습니다. 개인적인 경험으로 볼 때 디자인 패턴은 각 언어 (및 프레임 워크)가 언어에 구애받지 않는 경향이 있습니다. 특정 선택을 명백하게하고 특정 다른 선택을 매우 어렵게 만드는 자체 강점/약점.

어쨌든 토론에 제 2 ¢! :)

1

, 나는이 방법으로 갈거야 ... 이제 헛소리 그만하고 어떤 피드백을 기다린 다음 아마도 내가 붙어있어 정확한 위치에 대한 자세한 해명을 추가 할 것입니다 :

GUI 구성 요소를 제공하는 Extender (플러그인에서 제공하는 확장 구현)는 getTriad (나중에 더 나은 이름이 생깁니다) 메서드를 사용하여 MVP 트라이어드를 인스턴스화하고 연결하고 반환합니다. View에는 부모 컨테이너에 추가 할 수있는 프레임 워크 관련 GUI 요소 컨테이너 (부모 뷰 내에 캡슐화 된 프레임 워크 관련 세부 정보)를 렌더링하고 반환하는 getComponent 메서드가 있습니다. 뷰 자체를 컨테이너로 렌더링하는 대신 부모 뷰가 자식을 자체 렌더링하도록하는 것은 아닙니다. 나는 이것이 부모 Views를 직접적으로 엉망으로하지 않는 child Views를 보장하는 관점에서 더 좋다고 생각한다.

2

당신이 생각하는 디자인 패턴은 중재자입니다.

나는 중재자로 구성된 자바 스크립트 프레임 워크를 작성했습니다.

  • 당신은 중재자의 전역 인스턴스를 생성, 특정 이름 아래
  • 레지스터 개체,
  • 등록의 방법 를 호출 구현에 중재자를 사용

    그것은 다음과 같이 작동 오브젝트가 중 하나 내에 있습니다.

뭔가가 존재하지 않으면 오류가 발생하지 않습니다. 여러 인스턴스가있는 경우 모두 호출됩니다.

이 기본이에 대한 코드입니다)

을 (.. 내 코드의 추출물은 당신이 사용하고자하는 경우 한 동안 그것은 나를 빨리 그것을 밀어 것을 포함하여 jQuery 플러그인을 만들 것입니다)
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; 
      } 
     } 

    } 
+0

@David Murdoch. David에게 감사드립니다. 대문자는 내가 사는 "You"가있는 사람들을 언급 할 때 사용됩니다. 참고 : 당신이 뭔가를 귀찮게하기 때문에 사람들의 대답을 편집해서는 안됩니다. 누군가 불쾌 해 할 수도 있습니다. – naugtur

관련 문제