Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Фабрика не должна отдавать объекты? (http://www.flasher.ru/forum/showthread.php?t=184557)

Fintch 21.09.2012 18:32

Фабрика не должна отдавать объекты?
 
Здравствуйте!

Изучаю замечательную книгу Шаблоны проектирования (Design Patterns) O'REILLY.
Первый шаблон в этой книге - Фабричный метод (Factory Method).

Этот шаблон помогает создавать множество типов объектов через обращение в одну общую точку, так называемую фабрику.
Во всех примерах в этой книге фабрика не отдает объект. Она создает объект и сама же выполняет манипуляции с ним.

Но если я хочу управлять объектом вне фабрики?
Правильно ли будет изменить фабрику так, чтобы она возвращала этот объект или это противоречит шаблону?

Приведу примерный код минималистического примера из книги:
Код AS3:

package example {
 
    public interface IObject {
 
        function manipulate():void;
 
    }
 
}
 
package example {
 
    internal class Object1 implements IObject {
 
        public function Object1():void {
 
            super();
 
        }
 
        public function manipulate():void {
 
            trace("Doing stuff with Object1");
 
        }
 
    }
 
}
 
package example {
 
    internal class Object2 implements IObject {
 
        public function Object2():void {
 
            super();
 
        }
 
        public function manipulate():void {
 
            trace("Doing stuff with Object2");
 
        }
 
    }
 
}
 
package example {
 
    public class Factory {
 
        // Abstract Class
        public function Factory():void {
 
            super();
 
        }
 
        public function doStuff():void {
 
            var object:IObject = this.factoryMethod();
            object.manipulate();
 
        }
 
        protected function factoryMethod():IObject {
 
            // abstract method
            return null;   
 
        }
 
    }
 
}
 
package example {
 
    public class Factory1 extends Factory {
 
        public function Factory1():void {
 
            super();
 
        }
 
        override protected function factoryMethod():IObject {
 
            return new Object1();   
 
        }
 
    }
 
}
 
package example {
 
    public class Factory2 extends Factory {
 
        public function Factory2():void {
 
            super();
 
        }
 
        override protected function factoryMethod():IObject {
 
            return new Object2();   
 
        }
 
    }
 
}
 
package {
 
    public class Main extends Sprite {
 
        public function Main():void {
 
            super();
 
            var factory1:Factory1 = new Factory1();
            var factory2:Factory2 = new Factory2();
 
            factory1.doStuff();
            factory2.doStuff();
 
        }
 
    }
 
}

Вот в этом месте:
Код AS3:

public function doStuff():void {
 
    var object:IObject = this.factoryMethod();
    object.manipulate();
 
}

Можно так:
Код AS3:

public function doStuff():IObject {
 
    var object:IObject = this.factoryMethod();
    object.manipulate();
    return object;
 
}

И в Main так:
Код AS3:

public function Main():void {
 
    super();
 
    var factory1:Factory1 = new Factory1();
    var factory2:Factory2 = new Factory2();
 
    var object1:IObject = factory1.doStuff();
    var object2:IObject = factory2.doStuff();
 
    // затем манипуляции с object1 и object2
 
}

Или все это противоречит замыслу фабрики?
Если да, то как управлять объектами после создания в фабрике?
Поделитесь пожалуйста опытом :)

in4core 21.09.2012 18:38

Что то как то странно, поидее фабрика должна выглядеть так

Код AS3:

public function Main():void {
 
    super();
 
    var factory1:Factory1 = new Factory1();
    var factory2:Factory2 = new Factory2();
 
    var object1:IObject = factory1.getObject();
    var object2:IObject = factory2.getObject();
 
    // затем манипуляции с object1 и object2
    object1.manipulate();
 
}

Толи лыжи не едут, толи книга че то врет :)

Тоесть логично рассуждая : Клиент звонит на фабрику и спрашивает , а не могли ли бы вы мне завернуть 5 коробок дюлей? Ему говорят конечно - вот вам 5 коробок, но знайте что если пнуть коробку, она сама откроется

Код AS3:

var box:IBox = BoxesFactory.getBox();
box.kick()

Тоесть не фабрика должна открывать коробку, а клиент :)

С другой стороны тип фабрики может быть другой.
Например - ремонтная мастерская, это тоже фабрика , но по ремонту, и тогда мы уже говорим фабрике - почините мне 5 телевизиров 1ой марки )))

expl 21.09.2012 18:47

Не надо путать "абстрактную фабрику" и "фабричный метод".
А паттерн "просто фабрика" не является GoF-овским, если вообще является паттерном (хотя штука полезная и используется)

Фабричный метод вприципе может подразумевать использование объекта самим собой.
Это для изменения поведения объекта через наследование нужно и, на сам деле он то как раз на практике и используется и _очень_ часто, а "абстрактная фабрика" - не помню ни одного случая в своей практике. Ну может пару раз было.

Fintch 21.09.2012 19:03

@in4core : спасибо за пример)

@expl : А зачем нужна "абстрактная фабрика"?
Просто для подготовки объектов в одном месте?
И "простая фабрика" == "абстрактная фабрика" ?

in4core 21.09.2012 19:09

Ну абстрактная это так скажем пример. Это как говорить *в общем*. Так же как MVC - есть же такой паттерн, но никто ни слова не упоминает о том, что внутри могут быть реализации других паттернов и т.п.
Бред несу....)))

expl 21.09.2012 19:25

Цитата:

@expl : А зачем нужна "абстрактная фабрика"?
Просто для подготовки объектов в одном месте?
В каком-то смысле можно и так сказать.
Она представляет собой множество фабрик с одинаковым интерфейсом. И одна фабрика производит несколько типов объектов
Классический пример приводят - это разные скины всех контролов. Т.е. одна фабрика генерит контролы аля виндовс, другая - аля мак. А тот кто эти контролы располагает и связывает в игре просто при запуске подставляет одну из фабрик и везде if-ы не пишет.
Но штука громоздкая, потому не используется, или используется изредка во фреймворках.

Цитата:

И "простая фабрика" == "абстрактная фабрика" ?
Нет.
Простая фабрика это просто что угодно с публичным методом/методами newSomeObject():SomeObject.
Есть статическая простая фабрика - её методы статические.
Абстрактная фабрика подразумевает, что фабрик несколько и они имеют общий интерфейс - абстрактную фабрику

Ну вот не хочется вам кнопку по 10 раз настраивать в 10 местах - вы делаете метод "newCustomizedButton", в котором её создаёте и настраиваете. А во всех частях вместо 5 строк кода пишете одну - MyFactory.newCustomizedButton(); Это простая статическая фабрика

Или вот Вы создаете список с рендерерами во flex. Чтобы он отображал рендереры класса MyRenderer вы туда передаёте фабрику с интерфейсом:
Код AS3:

interface IFactory {
  function newInstance():*
}

Например это ClassFactory, ну new ClassFactory(MyRenderer) вы туда передаёте. А вот это _простая_ нестатическая фабрика

А вот если бы было так:
Код AS3:

interface IFactory {
  function newSelectedRenderer():ISelectedRenderer// В нашем придуманном списке этот рендерер используется чтобы отображать выбранные данные
  function newRenderer():IRenderer// а этот - все остальные
}

Это уже тянет на абстрактную фабрику. Но обычно просто 2 ClassFactory проще передать, чем этот интерфейс городить. Хоня не всегда.

Fintch 22.09.2012 10:09

Цитата:

А вот если бы было так:
Код AS3:
Код AS3:

interface IFactory {
  function newSelectedRenderer():ISelectedRenderer// В нашем придуманном списке этот рендерер используется чтобы отображать выбранные данные
  function newRenderer():IRenderer// а этот - все остальные
}

Это уже тянет на абстрактную фабрику. Но обычно просто 2 ClassFactory проще передать, чем этот интерфейс городить. Хоня не всегда.
@expl : Извините, с последним примером не могу разобраться.
То есть для каждого рендера свой интерфейс?
Я думал создается просто несколько рендеров с одним интерфейсом и несколько фабрик, которые работают через единый интерфейс рендера. Одна фабрика - один тип рендера? Нет?

expl 22.09.2012 15:45

Вы наверно не разобрались потому что я искусственный пример привёл.
Но объясню этот дурацкий пример до конца:

Цитата:

То есть для каждого рендера свой интерфейс?
Да, чтобы подчеркнуть что эта фабрика ещё и разных интерфейсов объекты создаёт я здесь сделал их разными.

Т.е. есть одна фабрика (ARedGreed implements IFactory), которая создает красные (RedSelectedRenderer implements ISelectedRenderer) и зелёные (GreenRenderer implements IGreenRenderer)
а есть другая фабрика (ABlueYellow implements IFactory), которая создает синие (BlueSelectedRenderer implements ISelectedRenderer) и желтые (YellowRenderer implements IGreenRenderer)

А визуальный список принимает, например, в конструктор IFactory, запоминает её, и когда надо что-то выделить - создаёт новый рендерер с newSelectedRenderer, а когда не надо - просто newRenderer

Ну и понятно, что не всегда надо делать отдельные классы YellowRenderer и GreenRenderer - можно просто написть newRenderer():IRenderer { return new CommonRenderer(0xffff00); }.

P.S. Вот хороший пример зачем используются фабрики вообще: http://gonchar.me/blog/goncharposts/411

Котяра 22.09.2012 17:13

Я использовал абстрактные фабрики довольно часто.
Вот пример. У меня есть абстрактный плагин в котором определено создание визуального объекта и прочее.
там есть строчка в методе создания вьюшек по модели:
Код AS3:

var view: IView= _viewFactory.create(viewModel);

В наследниках абстрактного плагина я инжектирую нужную фабрику _viewFactory, и в одном случае плагин по данным модели будет создавать красный кубик, в другом зелёный.
Можно этого же добиться переопределением абстрактного метода createView в наследниках, но тогда начинаются проблемы с наследованием и копипастой, а фабрика позволяет использовать композицию.


Часовой пояс GMT +4, время: 17:55.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.