Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   MVC+S + шаблон Фабрика ( Factory ) (http://www.flasher.ru/forum/showthread.php?t=202797)

Akopalipsis 12.08.2013 01:05

MVC+S + шаблон Фабрика ( Factory )
 
Начав читать интереснейшие статьи про различные паттерны проектирования, я стал их заложником.
Все они хорошие, все призваны упростить и улучшить код, но хорошее не всегда лучшее и чтобы не отклониться от курса, очень хочется, чтобы опытные, матёрые "кутюрье интернета", поделились секретами о структурировании и создании классов.
И эту тему я создал не из любопытства, а как уже упомянул ранее, из-за неоднозначных слов про то, что "абстрактную фабрику" в проектах не используют. Хоть такой паттерн и есть, но он как я понял не для жизни. И там же говорилось о "обычной фабрике" о которой я не понял не чего..
ГУРУ ?

Добавлено через 13 часов 26 минут
Код AS3:

class Factory {
        private static const ITEMS:Vector.<Class> = Vector.<Class>([Sword, Shield, Boots]);
        public static function createItem(id:uint):IItem {
                return new ITEMS[id]() as IItem;
        }
}
// ... somewhere
var item:IItem = Factory.createItem(2); // новый экземпляр класса Boots

Код AS3:

 Вы ожидали код 15-ти классов? Обычная фабрика это не паттерн.

Нет конечно, этого вполне достаточно. Спасибо!. Просто дело вот в чем - "обычная фабрика", это класс, экземпляр которого мы по прежнему не создаём. Мы обращаемся к нему и просим дать нам "что то"(с id 2);
Ну ведь так же и "абстрактная фабрика" устроенна - это тоже класс, экземпляр которого мы не создаем...

Dukobpa3 12.08.2013 14:51

Так и есть. Просто в обиходе не заморачиваются и абстрактную фабрику называют фабрикой. Паттерн фабрика впринципе один. Тут путаницы быть не должно.

И там были еще вопросы про фабричный метод.
Фабричный метод это фабричный метод. Фабричный метод может быть одним из вариантов реализации фабрики.

Wolsh 12.08.2013 17:14

какой-то ужас написали... ладно, названия классов и методов перепутаны, я еще могу как-то сопоставить. Но оверрайд не может быть с другой сигнатурой
Цитата:

"обычная фабрика", это класс, экземпляр которого мы по прежнему не создаём.
Создавайте, кто ж мешает. Я для простоты привел пример со "статическим" классом, точнее, пример класса фабрики со статическим методом. Но это же абсолютно не принципиально. Для обычной фабрики.
А вот абстрактная тем и отличается, что её экземпляр создать невозможно, потому что он абстрактный. (в моем примере Фабричного метода это был бы интерфейс ЯЗавод. Вы ведь не можете создать экземпляр интерфейса?). Вы создаете экземпляры классов-наследников, и используете их, подставляя нужный. ОК, давайте простой пример. Шахматы. Есть белые и черные фигуры. Есть Абстрактная фабрика с шестью методами, создающими экземпляры фигур — коня, короля, ферзя и т.д. И два класса-наследника, белая фабрика и черная фабрика. Ваше приложение знает ТОЛЬКО абстактную фабрику, у которой можно запросить коня или ладью. Оно не знает, будет конь белым или черным. Или серобуромалиновым в крапинку. Кто-то свыше устанавливает режим "белый", и место абстрактной фабрики занимает конкретная Белая фабрика, которая может отдавать только белых коней и королей. Вот и весь фокус. Это всего-лишь обычный полиморфизм. Клиент не знает, с каким конкретно классом работает, потому что работает с абстрактным суперклассом или интерфейсом. И какой конкретный класс будет производить набор фигур, решается в другом месте. В этом суть паттерна Абстрактная Фабрика. Похоже это хоть чем-то на обычный класс, производящий экземпляры? Смотреть то надо не на результат, а на решаемую задачу. А задачи у них абсолютно разные.

Dukobpa3 12.08.2013 17:20

Холивары про паттерны - это зло.
Надо думать как задачу решить, а не как назвать решение))

dimarik 12.08.2013 22:10

Абстрактная фабрика производит конкретные фабрики, которые вы используете для получения конкретного продукта.

Код AS3:

// новый экземпляр фабрики типа IHouseFactory.
const factory:IHouseFactory = AbstractFactory.create("И-522а");

Теперь factory — это фабрика домов типа И-522а
Все фабрики, выпускаемые фабрикой AbstractFactory имеют тип интерфейса IHouseFactory, который умеет производить части дома: фундамент createBasement, окна createWindow, перекрытия, лестничные пролеты и прочая конкретного типа домов (серии).

Код AS3:

const basement:IBasement = factory.createBasement(); // Фундамент серии "И-522а" готов!
const window:IWindow = factory.createWindow(); // Окно серии "И-522а" готово!
 
basement.addWindow(window); // Собрали дом серии И-522а;

Домашнее задание: построить дом серии И-700а.


ЗЫ. Почитателям друпального агрегатирования привет от инди-разработчика!

Akopalipsis 12.08.2013 22:12

Вложений: 1
Цитата:

какой-то ужас написали...
Сорри... даже не буду говорить из-за чего такой код, сами понимаете. Буду исправлять, как раз на шахматах.
Начну с "Абстрактной Фабрики".

Код AS3:

package chess.factory 
{
        import flash.display.Sprite;
 
        internal class Figure extends Sprite
        {
                //метод для переопределения
                internal function drawFigure():void
                {
                        //
                }
        }
 
}

Код AS3:

package chess.factory 
{
        internal class BlackHorse extends Figure
        {
                override internal function drawFigure():void
                {
                        trace('BlackHorse');
                }
        }
 
}

Код AS3:

package chess.factory 
{
        internal class BlackQueen extends Figure
        {
                override internal function drawFigure():void
                {
                        trace('BlackQueen');
                }
        }
 
}

Код AS3:

package chess.factory 
{
        internal class WhiteHorse extends Figure
        {
                override internal function drawFigure():void
                {
                        trace('WhiteHorse');
                }
        }
 
}

Код AS3:

package chess.factory 
{
        internal class WhiteQueen extends Figure
        {
                override internal function drawFigure():void
                {
                        trace('WhiteQueen');
                }
        }
 
}

Код AS3:

package chess.factory 
{
        public class BlackFigure extends FactoryFigure
        {
                public static const BLACK_HORSE : uint = 0x143423;
                public static const BLACK_QUEEN : uint = 0x331236;
 
                override public function createFigure(id:uint):Figure
                {
                        if (id == BLACK_HORSE)
                        {
                                trace('BlackFigure create BLACK_HORSE');
                                return new BlackHorse();
                        }
                        else
                        if (id == BLACK_QUEEN)
                        {
                                trace('BlackFigure create BLACK_QUEEN');
                                return new BlackQueen();
                        }
                        else
                        {
                                trace('ERROR BLACKFIGURE');
                                throw new Error('ERROR');
                        }
                }
        }
 
}

Код AS3:

package chess.factory 
{
        public class WhiteFigyre extends FactoryFigure
        {
                public static const WHITE_HORSE : uint = 0xFFFFFF;
                public static const WHITE_QUEEN : uint = 0xE4E7ED;
 
                override public function createFigure(id:uint):Figure
                {
                        if (id == WHITE_HORSE)
                        {
                                trace('WhiteFigyre create WHITE_HORSE');
                                return new WhiteHorse();
                        }
                        else
                        if (id == WHITE_QUEEN)
                        {
                                trace('WhiteFigyre create WHITE_QUEEN');
                                return new WhiteQueen();
                        }
                        else
                        {
                                trace('ERROR WHITEFIGYRE');
                                throw new Error('ERROR');
                        }
                }
        }
 
}

Код AS3:

package chess.factory 
{
        import flash.errors.IllegalOperationError;
 
        public class FactoryFigure
        {
                public function draw(id:uint):void
                {
                        var figure:Figure = createFigure(id);
                }
 
                public function createFigure(id:uint):Figure
                {
                        throw new IllegalOperationError('ERROR');
                        return null;
                }
        }
 
}

Код AS3:

package chess 
{
        import chess.factory.BlackFigure;
        import chess.factory.FactoryFigure;
        import chess.factory.WhiteFigyre;
        import flash.display.Sprite;
 
        public class Main extends Sprite
        {
 
                public function Main()
                {
                        /**
                        * public static const WHITE_HORSE : uint = 0xFFFFFF;
                        * public static const WHITE_QUEEN : uint = 0xE4E7ED;
                        */

                        var whiteHorse:FactoryFigure = new WhiteFigyre();
                        whiteHorse.draw(0xFFFFFF);
                        /**
                        * public static const BLACK_HORSE : uint = 0x143423;
                        * public static const BLACK_QUEEN : uint = 0x331236;
                        */

                        var blackHorse:FactoryFigure = new BlackFigure();
                        blackHorse.draw(0x143423);
                }
 
        }
 
}


Akopalipsis 12.08.2013 22:20

Цитата:

и место абстрактной фабрики занимает конкретная Белая фабрика
То есть моё зацикливание на слове "фабрика" имеет более простую основу чем мне казалось.
Если я в классе Main ( как в моём примере ) сразу обращаться к классу Белые фигуры, то это и будет "просто фабрика" ?

dimarik 12.08.2013 22:39

Нет BlackFigure, WhiteFigyre. Есть конь, ладья, дама, валет и туз. Они производятся на фабриках черных, белых, пика, трефи, бубна и черви. Они (шахматные фигуры или игральные карты) из одной фабрики получаются одного цвета (масти), на которую заточена конкретная фабрика. Прораб утром оглашает план работ: "Каждую четверть дня делать карты следующей масти". Вот, работяги, вам старый знакомый аппарат с набором кнопок, которые выпускают карты по номиналу. Кнопка "валет" выдает номинал... валета, кнопка "2" - простую двоечку. И он подсовывает аппарат, выпускающий все номиналы масти треф. Через четверть рабочего дня меняет на аппарат с такими же кнопками, но выпускающий все номиналы масти бубна. Следующие два аппарата выпускают масти черва и пика. Упаковывающая бригада раскладывает готовую продукцию по колодам и упаковывает их.

Akopalipsis 12.08.2013 23:22

Цитата:

Нет BlackFigure, WhiteFigyre.
Вы наверное ошиблись, не должно быть WhiteHorse и BlackHorse, вместо них должно быть Horse и две фабрики - BlackFigure и WhiteFigyre. Да? Или это я ещё раз ошибся?)

Wolsh 12.08.2013 23:39

dimarik, хороший пример, спасибо)))

У GoF тоже нормальный пример (мой конечно не очень логичен)) — есть некий интерфейс (GUI) приложения, скажем кнопка, скроллбар, дропменю и чекбокс. И есть два (или больше) стилей для отображения этого интерфейса. Допустим, приложение может выглядеть в стиле Windows, а может в стиле MacOS. Самому приложению совершенно все равно, как выглядят эти кнопки и бары, но они, конечно же, должны соответствовать своим типам, чтобы можно было задавать им значения и запрашивать их.
У приложения есть класс или функция, который должен создать и расставить элементы интерфейса. Он обращается к фабрике, которая представлена Абстрактным Классом или Интерфейсом, и получает от нее экземпляры кнопок и т.п.
Код AS3:

var factory:IGUIFactory;
//... где-то происходит инициализация factory
//... допустим таким образом: factory = AbstractFactory.create("MacOS");
//... затем фабрика создает экземпляры
var scrollbar:IScrollbar = factory.createScrollbar();
var button:IButton = factory.createButton();
var checkbox:ICheckbox = factory.createCheckbox();
var menu:IMenu = factory.createMenu();

Таким образом, заменяя конкретную фабрику, можно получать НАБОР элементов одного стиля (все белые или все черные фигуры, все карты одной масти, все контролы одного стиля). Приложению не нужно знать, какие именно классы будут их производить. Эти классы можно писать отдельно и заменять в любой момент, не трогая остальной код.

Akopalipsis 13.08.2013 01:47

dimarik я чувствую себя просто хамом не поблагодарив Вас за столь прекраснейшей пример! Посмотрев на него в первый раз и второй и третий, я понял, что на нем я понимаю, да и на картах вроде... А вот на шахматах, как будто не совсем. По этому я и уточнил - ошибся... Ой!) Опять! Спасибо!.. по этому я и уточнил - ошибся ли я в своём предположении о фабриках... и -
Цитата:

не должно быть WhiteHorse и BlackHorse, вместо них должно быть Horse и две фабрики - BlackFigure и WhiteFigyre.
Wolsh Спасибо Вам! я предполагаю, что вы тоже знаете ответ на мой глупый вопрос...?)

Wolsh 13.08.2013 01:54

WhiteHorse и BlackHorse могут быть, почему нет. Только они должны расширять AHorse или имплементить IHorse :) И одного из них будет возвращать белая фабрика, а второго — черная.

Akopalipsis 13.08.2013 01:59

Wolsh Спасибо Вам огромное за помощь и столь развернутые ответы на мои глупые вопросы! Пойду ещё практиковаться и вроде уже завершу для себя главу с фабриками.. Хотя, я ещё вернусь и спрошу про то, как лучше совмещать несколько фабрик)

Akopalipsis 14.10.2013 02:56

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

Dukobpa3 14.10.2013 03:04

ниче не понял


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

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