Управление жизненным циклом Model-View-Presenter в графическом интерфейсе на основе плагинов - PullRequest
2 голосов
/ 17 августа 2010

Когда GUI состоит из нескольких подкомпонентов, которые я рассматриваю как отдельные представления с их собственными Presenter и Models, существует ли шаблон для их склеивания?Некоторые подкомпоненты постоянно отображаются на экране, в то время как другие меняются местами.

  1. Какой будет хороший фабричный шаблон для создания экземпляра соответствующей триады MVP для подкомпонента, который добавляется в GUI во время выполнения?
  2. Как вы склеиваете подкомпоненты с постоянной «контейнерной» частью GUI и друг с другом?Будет ли «Бог-предъявитель», который связывает других докладчиков?

Обновление: Сейчас я снимаю что-то похожее на механизм расширения Eclipse.Плагины регистрируют себя в глобальном реестре для функциональности, которую они предоставляют.Когда необходима такая функция, как возврат данных или отображение представления, запрашивается реестр и возвращаются функции (это чистый JavaScript, поэтому я не использую интерфейсы).Я иду с подходом чистого плагина, где все (даже основной вид) является плагином.Я также мог бы использовать шину событий, чтобы позволить различным докладчикам взаимодействовать друг с другом.

Теперь мой более конкретный вопрос возникает, когда плагин собирается добавить представление, как мне следует инициализировать триаду MVP иполучение представления, отображаемого в родительский контейнер (вне модуля).Мне, вероятно, нужно позволить представлению визуализировать себя в контейнер, переданный извне, и добавить представление и модель (при необходимости) в Presenter.Альтернативой было бы для View возвращать компонент, который может быть помещен в контейнер, но это противоречило бы моему предварительному идеалу хранить все, что является специфичным для GUI-фреймворка, внутри реализаций View.Я предпочитаю, чтобы фабричный / клеевой механизм мог быть независимым от фреймворка.

Хорошо, я перестану болтать сейчас и подожду отзывов, а затем, возможно, добавлю больше разъяснений, где именно я застрял ...

Ответы [ 3 ]

2 голосов
/ 29 сентября 2010

Я думаю, что шаблон дизайна, о котором вы говорите, - mediator .

Я написал фреймворк javascript, состоящий из посредника.

Работает так:

  • Вы создаете глобальный экземпляр посредник,
  • регистрация объектов под определенные имена,
  • используйте посредник в своей реализации для вызова методов из зарегистрированных объектов в любом из объекты.

Если чего-то нет - ошибки не летают. Если есть несколько экземпляров - они все получают вызов.

Это основной код для этого: (Выдержка из моего кода. Я сделаю плагин 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;
            }
        }

    }   
1 голос
/ 28 сентября 2010

Полагаю, что "сохранение специфической для GUI-среды структуры внутри реализаций View" - это общий выбор дизайна на уровне приложения, а не абсолютная необходимость (по крайней мере, если вы думаете, что "просмотр реализации" следует рассматривать как"реализация представления плагина").

Вы можете, например, иметь очень тонкий слой представления на уровне плагина и реализовать слой суперпросмотра в родительском элементе, который вызывает плагины: мышление для системы плагиновчтобы все добавили столбец в таблицу, вы могли бы иметь большую часть кода представления на родительском уровне («таблица») и иметь свои плагины, чтобы просто передавать немного больше, чем необработанные данные: вы избежали бы повторения и сделали быкод более гибкий и обслуживаемый.

С другой стороны, если ваши плагины предоставляют очень разные типы функций, которые никогда не взаимодействуют напрямую (например, если они являются различными подсистемами симулятора полета), вы захотите сохранить всеэто связано с представлениями на уровне плагина, так что родительский объектНе нужно даже знать, с чем имеет дело данный плагин, а просто поместить его возвращаемое значение где-нибудь в GUI.

Другими факторами, которые могут повлиять на ваш выбор, являются язык и структура (если таковые имеются), которые вы используете.Использую: по моему личному опыту, шаблоны проектирования, как правило, далеки от языковой независимости, поскольку каждый язык (и структура) имеет свои сильные и слабые стороны, которые делают определенные выборы очевидными, а некоторые другие очень сложными для реализации.

Просто мои 2 ¢ к обсуждению, так или иначе!:)

1 голос
/ 27 сентября 2010

Сейчас я иду с этим подходом:

Расширитель (реализация расширения, предоставляемая плагином), который вносит компонент GUI, имеет getTriad (придет случше назовите позже) метод, который создает экземпляр, соединяет и возвращает триаду MVP.В представлении есть метод getComponent, который визуализирует и возвращает контейнер элемента GUI, специфичный для каркаса, который можно добавить в родительский контейнер (специфичные для каркаса детали которого инкапсулированы в родительских представлениях).Я не позволяю View визуализировать себя в контейнер, а вместо этого позволяю родительскому View визуализировать дочерний элемент в себя.Я думаю, что это лучше с точки зрения обеспечения того, чтобы дочерние представления напрямую не связывались с родительскими представлениями.

...