Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > ActionScript 3 > Паттерны ООП


Автор: AntonioBanderaz 31.10.2006, 11:55
При проектировании приложений, а на Flash это RIA, часто возникает необходимость сообщить многим объектам какую либо информацию, сообщение. Для 
этого правильно испьзовать паттерн проектирования Observer. Паттерн проектирования Observer описывает отношение между объектами типа N к 1, и при 
изменении состояния одного происходит автоматическое уведомление и обновление всех зависящих от него объектов. 
Что нужно для базовой реализации паттерна. 

    1. Интерфейс Observer, имплементируют все слушатели
    2. Класс сообщения, объекты которого получают все слушатели.
    3. Класс Observable, класс регистрирующий слушателей и рассылающий сообщения.

Интерфейс Observer
Observer.as
Код

package com.avelichko.pattern.observer
{
    public interface Observer
    {
        public function update(o:Observable, msg:ObserverMessage):void;
    }
}



Класс сообщения ObserverMessage
ObserverMessage.as
Код

package com.avelichko.pattern.observer
{
    import com.avelichko.lang.util.exceptions.NullPointerException;
    
    public class ObserverMessage
    {
        private var _type:int = 0;
        private var _object:Object = null;
        
        public function set type(t:int):void {
            _type = t;
        }
        
        public function get type():int {
            return _type;
        }
        
        public function set msg(o:Object):void {
            if(o == null) {
                throw new NullPointerException("ObserverMessage must be not null");
            }
            _object = o;
        }
        
        public function get msg():Object {
            return _object;
        }
    }
}


Класс Observable
Observable.as
Код

package com.avelichko.pattern.observer
{
    import com.avelichko.lang.util.ArrayList;
    import com.avelichko.lang.util.Collection;
    import com.avelichko.lang.util.Iterator;
    import com.avelichko.lang.util.exceptions.NullPointerException;
    import com.avelichko.pattern.exceptions.DuplicateObserverException;
    
    public class Observable
    {
        
        private var inUse:Boolean = false;
        
        private var observersStack:Collection;
        private var observers:Collection;
        
        public function Observable() {
            observers = new ArrayList();
        }
        
        public function addObserver(o:Observer):void {
            
            if(o == null) {
                throw new NullPointerException("Observer object must be not null");
            }
            if(observers.contains(o)) {
                throw new DuplicateObserverException("Observer list already contains this observer");
            }
            if(inUse) {
                observersStack.add(o);
            } else {
                observers.add(o);
            }
        }
        
        public function removeObserver(o:Observer):void {
            var it:Iterator = observers.iterator();
            while(it.hasNext()) {
                var ob:Observer = it.next().valueOf();
                if(ob == o) {
                    it.remove();
                }
            }
        }
        
        public function notifyObservers(msg:ObserverMessage):void {
            if(!observersStack.isEmpty()) {
                var it:Iterator = observersStack.iterator();
                while(it.hasNext()) {
                    addObserver(it.next());
                }
            }
            
            inUse = true;
            
            var it:Iterator = observers.iterator();
            while(it.hasNext()) {
                var obs:Observer = it.next().valueOf();
                obs.update(this, msg);
            }
            
            inUse = false;
        }
        
        public function clearObservers():void {
            observers.clear();
            observersStack.clear();
        }
        
        public function countObservers():int {
            return observers.size() + observersStack.size();
        }
    }
}


Вспомогательный класс DuplicateObserverException
DuplicateObserverException.as
Код

package com.avelichko.pattern.exceptions
{
    public class DuplicateObserverException extends Error
    {
        public function DuplicateObserverException(message:String="", id:int=0)
        {
            super(message, id);
        }
        
    }
}



Собственно все, теперь надо идти к конкретной реализации этого паттерна, расширят класс Observable, имплементировать Observer, расширять 
ObserverMessage. Я привёл только базовую реализацию.

Теперь более сложный паттерн, так называемый mvc (Model-View-Controller). Иделогия mvc разделить обратную связь с пользователем, или неким 
интерфейсом разделены явно и обрабатываются тремя разными типами объектов. 
MVC состоит модели(Model) представления(View) и контроллера(Controller) 

    1. Модель - Хранит данные и логику интерфейса
    2. Представление - генерирует правльное визульное представление интерфейса.
    3. Контроллер - отвечает за вводимые данные, изменяя модель.

Не буду расписывать что-что делает думаю будет понятно, времени нет вообще, просто выложу классы.
Controller.as
Код

package com.avelichko.pattern.mvc
{
    import com.avelichko.pattern.observer.Observable;
    
    public interface Controller
    {
        function setModel(m:Observable):void;
        
        function getModel():Observable;
        
        function setView(v:View):void;
        
        function getView():View;
    }
}


View.as
Код

package com.avelichko.pattern.mvc
{
    import com.avelichko.pattern.observer.Observable;
    
    public interface View
    {
        function setModel(o:Observable):void;
        
        function getModel():Observable;
        
        function setController(c:Controller):void;
        
        function getController():Controller;
        
        function defaultController(model:Observable):Controller;
    }
}


AbstractController.as
Код

package com.avelichko.pattern.mvc
{
    import com.avelichko.pattern.observer.Observable;
    import com.avelichko.lang.util.exceptions.NullPointerException;

    public class AbstractController implements Controller
    {
        private var model:Observable = null;
        private var view:View = null;
        
        public function AbstractController(m:Observable) {
            setModel(m);
        }
        
        public function getView():View
        {
            return view;
        }
        
        public function setModel(m:Observable):void
        {
            if(m == null) {
                throw new NullPointerException("model must be not null");
            }
            model = m;
        }
        
        public function setView(v:View):void
        {
            if(v == null) {
                throw new NullPointerException("view must be not null");
            }
            view = v;
        }
        
        public function getModel():Observable
        {
            return model;
        }
        
    }
}


AbstractView.as
Код

package com.avelichko.pattern.mvc
{
    import com.avelichko.pattern.observer.Observer;
    import com.avelichko.pattern.observer.ObserverMessage;
    import com.avelichko.pattern.observer.Observable;
    import com.avelichko.lang.util.exceptions.NullPointerException;

    public class AbstractView implements Observer, View
    {
        
        private var model:Observable = null;
        private var controller:Controller = null;
        
        public function AbstractView(m:Observable, c:Controller = null) {
            if(o == null) {
                throw new NullPointerException("Model must be not null");
            }
            setModel(o);
            if(c != null) {
                setController(c);
            }
        }
        
        public function update(o:Observable, msg:ObserverMessage):void
        {

        }
        
        public function setModel(o:Observable):void
        {
            model = o;
        }
        
        public function getController():Controller
        {
            if(controller == null) {
                setController(defaultController(getModel()));
            }
            return controller;
        }
        
        public function getModel():Observable
        {
            return model;
        }
        
        public function defaultController(model:Observable):Controller
        {
            return null;
        }
        
        public function setController(c:Controller):void
        {
            if(c == null) {
                throw new NullPointerException("Controller must be not null");
            }
            controller = c;
            getController().setView(this);
        }
        
    }
}


Некое заключение. С помощью этих двух паттернов можно делать одинаковые вещи, но надо понимать что и для чего применимо в конкретной ситтуации. 
Паттерн MVC применяется в более сложных и больших проектах, в то время как Observer применяется для решения более простых задач... 

Автор: AlDev 31.10.2006, 12:33
Дополню:
что такое MVC - читайте тут:
http://ru.wikipedia.org/wiki/MVC

Автор: AntonioBanderaz 31.10.2006, 14:24
Цитата(AntonioBanderaz @  31.10.2006,  11:55 Найти цитируемый пост)

Теперь более сложный паттерн, так называемый mvc (Model-View-Controller). Иделогия mvc разделить обратную связь с пользователем, или неким 
интерфейсом разделены явно и обрабатываются тремя разными типами объектов. 
MVC состоит модели(Model) представления(View) и контроллера(Controller) 

Лажанул... 

Теперь более сложный паттерн, так называемый mvc (Model-View-Controller). Иделогия mvc разделить обратную связь с пользователем, или неким интерфейсом. Они разделены явно и обрабатываются тремя разными типами объектов: модели(Model), представления(View) и контроллера(Controller).

Так наверно будет понятней.

Автор: AlDev 1.11.2006, 09:35
про Observer - а чем не устраивает EventDispatcher? =)

Автор: AntonioBanderaz 1.11.2006, 12:55
Цитата(AlDev @  1.11.2006,  09:35 Найти цитируемый пост)
про Observer - а чем не устраивает EventDispatcher? =) 

Да всем устраивает, просто Observer проще.

Там ошибочки в классах Observer были. Подправил.

Автор: AlDev 6.11.2006, 13:25
так. терь про mvc - 
тут сильно кастрированый вариант smile 

Автор: AntonioBanderaz 7.11.2006, 10:45
Цитата(AlDev @  6.11.2006,  13:25 Найти цитируемый пост)
так. терь про mvc - 
тут сильно кастрированый вариант smile  

Всмысле кастрированый, что тебе тут не хватает?


Автор: AlDev 7.11.2006, 10:47
общение между m v и с. action-ы. Посмотри тот же struts smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)