а вот как раз обсуждали.. https://php.ru/forum/threads/fabrika-i-fabrichnyj-metod.66558/#post-539461 я сам плохо знаю эти паттерны..
Абстрактная фабрика - это класс, служащий для создания семейства потомков других абстрактных классов, каким-то образом связанных тематически. Вот короткие примеры для ООП всегда сложно выдумывать. А брать из реальных проектов - долго объяснять зачем оно там. Ну вот как пример: PHP: interface IStorage {/* ... */ } interface IFilter { /* ... */ } interface StorageAbstractFactory { public function getStorage(): IStorage; public function getFilter(): IFilter; } class MySQLStorageFactory implements IStorage { public function getStorage(): IStorage { return new MySQLStorage();} public function getFilter(): IFilter {return new MySQLFilter();} } Иначе говоря, если у тебя образовалось несколько параллельных иерархий, объединённых одной тематикой, то создания лучше доверить абстрактной фабрике, чтобы потом можно было подменять одну иерархию другой.
это правильный пример? PHP: <?php /** Наша абстрактная фабрика */ abstract class myFactory { /** точка входа в фабрику */ static public function getFactory(){ if(Base :: route['get']['mod'] == 'news') return new newsFactory(); else return new blogFactory(); } /** предполагаем что у дочерних классов должны быть методы */ abstract function createMes(); abstract function getError(); } /** класс новостей */ class newsFactory extends myFactory { public function createMes(){ return newsclass :: createMes(); } public function getError(){ return Base :: getError(); } } /** класс блога */ class blogFactory extends myFactory { public function createMes(){ return blogclass :: createMes(); } public function getError(){ return Base :: getError(); } } /** запускаем нашу абстрактную фабрику */ $factory = myFactory :: getFactory(); /** создаем новое сообщение */ $factory -> createMes(); /** смотрим ошибки */ $factory -> getError(); ?>
http://phpforum.su/index.php?showtopic=51604 тут пример взял --- Добавлено --- только я на пойму, что за класс Base тут?
Просто автор топика его не показал, как и остальные классы, не относящиеся напрямую к паттерну. А вообще, купи или скачай вот эту книжку, прочитай, вопросы отпасть должны: https://www.ozon.ru/context/detail/id/5648968/. И ещё вот этого дядьку послушай: , он, правда, джавист, но паттерны там все те же. Абстрактные фабрики можно на любом ОО-языке делать. --- Добавлено --- Ой, я хотел урлу вставить дяденьки. Ну вот сюда кликай, короче
PHP: <?php //Абстрактная фабрика - позволяет создавать семейства связанных объектов, // не привязываясь к конкретным классам создаваемых объектов. /* обобщённый интерфейс фабрики - Это как раз и есть Абстрактная фабрика - по этой сущности (этому классу) и назван весь паттерн */ abstract class AbstractBookFactory { abstract function makePHPBook(); abstract function makeMySQLBook(); } // конкретная книжная фабрика для издательства class OReillyBookFactory extends AbstractBookFactory { private $context = "OReilly"; function makePHPBook() { // метод создания книги о PHP return new OReillyPHPBook; } function makeMySQLBook() { // метод создания книги о MySQL return new OReillyMySQLBook; } } // конкретная книжная фабрика для издательства class SamsBookFactory extends AbstractBookFactory { private $context = "Sams"; function makePHPBook() { // метод создания книги о PHP return new SamsPHPBook; } function makeMySQLBook() { return new SamsMySQLBook;// метод создания книги о MySQL } } // далее класс книг (продукты) // абстрактная книга abstract class AbstractBook { abstract function getAuthor(); abstract function getTitle(); } // абстрактная книга по MYSQL abstract class AbstractMySQLBook extends AbstractBook { private $subject = "MySQL"; } // книга по MYSQL от издательства О'РЕйли class OReillyMySQLBook extends AbstractMySQLBook { private $author; private $title; function __construct() { $this->author = 'George Reese, Randy Jay Yarger, and Tim King'; $this->title = 'Managing and Using MySQL'; } function getAuthor() { return $this->author; } function getTitle() { return $this->title; } } // книга по MYSQL от издательства Самс class SamsMySQLBook extends AbstractMySQLBook { private $author; private $title; function __construct() { $this->author = 'Paul Dubois'; $this->title = 'MySQL, 3rd Edition'; } function getAuthor() { return $this->author; } function getTitle() { return $this->title; } } // абстрактная книга по PHP abstract class AbstractPHPBook extends AbstractBook{ private $subject = "PHP"; } // конкретная книга по PHP от издательства О'РЕйли class OReillyPHPBook extends AbstractPHPBook { private $author; private $title; private static $oddOrEven = 'odd'; function __construct() { //выбираем между двумя книгами if ('odd' == self::$oddOrEven) { $this->author = 'Rasmus Lerdorf and Kevin Tatroe'; $this->title = 'Programming PHP'; self::$oddOrEven = 'even'; } else { $this->author = 'David Sklar and Adam Trachtenberg'; $this->title = 'PHP Cookbook'; self::$oddOrEven = 'odd'; } } function getAuthor() { return $this->author; } function getTitle() { return $this->title; } } // конкретная книга по PHP от издательства Самс class SamsPHPBook extends AbstractPHPBook { private $author; private $title; function __construct() { //случайным образом выбираем одну книгу из двух mt_srand((double)microtime() * 10000000); $rand_num = mt_rand(0, 1); if (1 > $rand_num) { $this->author = 'George Schlossnagle'; $this->title = 'Advanced PHP Programming'; } else { $this->author = 'Christian Wenz'; $this->title = 'PHP Phrasebook'; } } function getAuthor() { return $this->author; } function getTitle() { return $this->title; } } writeln('<br><b>тестируем работу конкретной фабрики издательства OReilly</b><br>'); $bookFactoryInstance = new OReillyBookFactory; // создаём экземпляр фабрики // запускаем функцию тестирования передав в неё в качестве параметра // экземпляр нашей фабрики testConcreteFactory($bookFactoryInstance); // запустили тестирование writeln('<br><b>тестируем работу конкретной фабрики издательства Sams</b><br>'); $bookFactoryInstance = new SamsBookFactory; // создаём экземпляр фабрики testConcreteFactory($bookFactoryInstance); // запустили тестирование /* далее приводим код самой функции тестирование - она-то как раз и демонстрирует "удобство" применения паттерна Абстрактная фабрика */ function testConcreteFactory($bookFactoryInstance) // принимает объект конретной фабрики { // вызываем метод создания PHP книги - наш код не зависит от того какое именно издательство // передано (фабрика какого именно издательства передана) для реализации создания книг $phpBookOne = $bookFactoryInstance->makePHPBook(); writeln('Автор первой книги по PHP: '.$phpBookOne->getAuthor()); writeln('Заголовок первой книги по PHP: '.$phpBookOne->getTitle()); $phpBookTwo = $bookFactoryInstance->makePHPBook(); writeln('Автор второй книги по PHP: '.$phpBookTwo->getAuthor()); writeln('Заголовок второй книги по PHP:: '.$phpBookTwo->getTitle()); $mySqlBook = $bookFactoryInstance->makeMySQLBook(); writeln('Автор книги по MySQL: '.$mySqlBook->getAuthor()); writeln(' Заголовок книги по MySQL: '.$mySqlBook->getTitle()); } function writeln($line_in) { echo $line_in."<br/>"; } ?> вопрос, объясните, что тут происходит: PHP: function __construct() { //выбираем между двумя книгами if ('odd' == self::$oddOrEven) { $this->author = 'Rasmus Lerdorf and Kevin Tatroe'; $this->title = 'Programming PHP'; self::$oddOrEven = 'even'; } else { $this->author = 'David Sklar and Adam Trachtenberg'; $this->title = 'PHP Cookbook'; self::$oddOrEven = 'odd'; } } для чего нам $oddOrEven и что такое odd и even (строки)
Ну это они так чередуют просто, чтоб OReillyPHPBook то одно название, то другое выдавал. Это не часть паттерна, это просто люди попытались придумать короткий пример абстрактной фабрики, что очень непросто, поскольку это паттерн для решения сложных задач. Видно же, как они используют если odd, то автор Rasmus Lerdorf and Kevin Tatroe и меняется на even. Вы совсем код не читаете, такую элементарную вещь не видите? Сам паттерн здесь в том, что одна фабрика даёт книги по php и mysql от O'Reily, другая от Sams. Тут правда в примере главное не показано - какую из двух фабрик использовать, можно решить в процессе выполнения скрипта, на основе когфига или пользовательского ввода. Видите, у них testConcreteFactory() не знает, с какой она фабрикой работает, можно передать и орайли, и самс - она только знает, что реализует интерфейс AbstractBookFactory - ну это полиморфизм в действии. Если полиморфизм не понимаете, то паттерны вам рано, они все его так или иначе используют, и вообще, это единственная причина использовать ООП. Если не нужен полиморфизм, не нужно и ООП. --- Добавлено --- Любой короткий пример будет искусственным. Вот в книге, которую я рекомендую, там более-менее похожий на реал пример, но там страницы 4 о нём, я их сюда перепечатывать не буду.
Вот суть абстрактной фабрики. Всё. Теперь ты можешь сколько угодно создавать разных фабрик книг про php и mysql, функция testConcreteFactory будет работать с любой. То, на чём ты споткнулся почему-то, это уже конкретная реализация класса книги, объекты которых должны создавать фабрики, и она не важна. Но ты всё примеры только смотришь, теорию не хочешь рассматривать, я так понимаю. С ООП так не выйдет. За ООП стоит большой и сложный теоретический аппарат, в одном посте не опишешь. Я тебе дал название книги и ссылку на лекции, по которым это осваивал я. Почитай. Да, мой код улучшился после знакомства с этими материалами. Хотя не скажу, что у меня вот в каждом проекте куча абстрактных фабрик (или вообще фабрик). Паттерны изучаются не для того, чтобы пихать их везде, Короткий рабочий пример абстрактной фабрики, где она давала бы хоть какой-то смысл, ты не найдёшь. Увы. Если у тебя в проекте потребовалась абстрактная фабрика, значит он уже относительно крупный. --- Добавлено --- Один из базовых принципов ООП - интерфейс важнее реализации.
я наверно совсем торможу)) но odd и even вижу только в конструкторе используется.. более того $oddOrEven это даже не параметр конструктора, а приватное свойство.. значит при создании объекта мы никак не можем его поменять.. или просто этот код воспринимать как пример а не как что то рабочее))? Спасибо)
@Алекс8, оно статическое, т.е. общее для всех экземпляров классов, и каждый вызов конструктора его переключает с odd на even и обратно. См. строки 7 и 12 листинга, где конструктор отдельно. --- Добавлено --- Пример искусственный, но рабочий вроде.
ооо.. я слепошара.. действительно статик.. а я на private глянул а дальше пропустил)) спасибо большое))