За последние 24 часа нас посетили 22952 программиста и 1241 робот. Сейчас ищет 751 программист ...

Абстрактная фабрика

Тема в разделе "PHP для новичков", создана пользователем artemka, 22 окт 2017.

  1. artemka

    artemka Новичок

    С нами с:
    18 авг 2017
    Сообщения:
    56
    Симпатии:
    4
    Здравствуйте. Можете объяснить что такое абстрактная фабрика и привести пример с комментариями?
     
  2. Алекс8

    Алекс8 Активный пользователь

    С нами с:
    18 май 2017
    Сообщения:
    1.730
    Симпатии:
    359
    вроде как класс который создает объекты других классов..
     
  3. artemka

    artemka Новичок

    С нами с:
    18 авг 2017
    Сообщения:
    56
    Симпатии:
    4
    а пример можете привести? например тема фибрика автомобилей
     
  4. Алекс8

    Алекс8 Активный пользователь

    С нами с:
    18 май 2017
    Сообщения:
    1.730
    Симпатии:
    359
  5. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.555
    Симпатии:
    1.754
    Абстрактная фабрика - это класс, служащий для создания семейства потомков других абстрактных классов, каким-то образом связанных тематически. Вот короткие примеры для ООП всегда сложно выдумывать. А брать из реальных проектов - долго объяснять зачем оно там. Ну вот как пример:
    PHP:
    1. interface IStorage {/* ... */ }
    2. interface IFilter { /* ... */ }
    3. interface StorageAbstractFactory {
    4.    public function getStorage(): IStorage;
    5.    public function getFilter(): IFilter;
    6. }
    7.  
    8. class MySQLStorageFactory implements IStorage {
    9.     public function getStorage(): IStorage { return new MySQLStorage();}
    10.    public function getFilter(): IFilter {return new MySQLFilter();}
    11. }
    Иначе говоря, если у тебя образовалось несколько параллельных иерархий, объединённых одной тематикой, то создания лучше доверить абстрактной фабрике, чтобы потом можно было подменять одну иерархию другой.
     
  6. artemka

    artemka Новичок

    С нами с:
    18 авг 2017
    Сообщения:
    56
    Симпатии:
    4
    это правильный пример?

    PHP:
    1. <?php
    2.    
    3. /** Наша абстрактная фабрика */
    4. abstract class myFactory
    5. {
    6.   /** точка входа в фабрику */
    7.   static public function getFactory(){
    8.     if(Base :: route['get']['mod'] == 'news')
    9.       return new newsFactory();
    10.     else
    11.       return new blogFactory();
    12.   }  
    13.   /** предполагаем что у дочерних классов должны быть методы */
    14.   abstract function createMes();
    15.   abstract function getError();
    16. }
    17.    
    18. /** класс новостей */
    19. class newsFactory extends myFactory
    20. {
    21.   public function createMes(){
    22.     return newsclass  :: createMes();
    23.   }
    24.   public function getError(){
    25.     return Base :: getError();
    26.   }
    27. }
    28.    
    29. /** класс блога */
    30. class blogFactory extends myFactory
    31. {
    32.   public function createMes(){
    33.     return blogclass  :: createMes();
    34.   }
    35.   public function getError(){
    36.     return Base :: getError();
    37.   }
    38. }
    39.    
    40. /** запускаем нашу абстрактную фабрику */
    41. $factory = myFactory :: getFactory();
    42.    
    43. /** создаем новое сообщение */
    44. $factory -> createMes();
    45.    
    46. /** смотрим ошибки */
    47. $factory -> getError();
    48. ?>
     
  7. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.555
    Симпатии:
    1.754
    Ага. Только что у тебя вот тут:
     
  8. artemka

    artemka Новичок

    С нами с:
    18 авг 2017
    Сообщения:
    56
    Симпатии:
    4
  9. artemka

    artemka Новичок

    С нами с:
    18 авг 2017
    Сообщения:
    56
    Симпатии:
    4
    может кто-то объяснить?
    --- Добавлено ---
    тоьько я на поймУ, что так
     
  10. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.555
    Симпатии:
    1.754
    Просто автор топика его не показал, как и остальные классы, не относящиеся напрямую к паттерну. А вообще, купи или скачай вот эту книжку, прочитай, вопросы отпасть должны: https://www.ozon.ru/context/detail/id/5648968/. И ещё вот этого дядьку послушай: , он, правда, джавист, но паттерны там все те же. Абстрактные фабрики можно на любом ОО-языке делать.
    --- Добавлено ---
    Ой, я хотел урлу вставить дяденьки. Ну вот сюда кликай, короче
     
  11. artemka

    artemka Новичок

    С нами с:
    18 авг 2017
    Сообщения:
    56
    Симпатии:
    4
    PHP:
    1. <?php
    2. //Абстрактная фабрика - позволяет создавать семейства связанных объектов,
    3. // не привязываясь к конкретным классам создаваемых объектов.
    4.  
    5. /* обобщённый интерфейс фабрики -
    6. Это как раз и есть Абстрактная фабрика  - по этой сущности (этому классу)
    7. и назван весь паттерн
    8. */
    9.  
    10. abstract class AbstractBookFactory {
    11.     abstract function makePHPBook();
    12.     abstract function makeMySQLBook();
    13. }
    14.  
    15. // конкретная книжная фабрика для издательства
    16. class OReillyBookFactory extends AbstractBookFactory {
    17.     private $context = "OReilly";
    18.     function makePHPBook() { // метод создания книги о PHP
    19.         return new OReillyPHPBook;
    20.     }
    21.     function makeMySQLBook() { // метод создания книги о MySQL
    22.         return new OReillyMySQLBook;
    23.     }
    24. }
    25.  
    26. // конкретная книжная  фабрика для издательства
    27. class SamsBookFactory extends AbstractBookFactory {
    28.     private $context = "Sams";
    29.     function makePHPBook() { // метод создания книги о PHP
    30.         return new SamsPHPBook;
    31.     }
    32.     function makeMySQLBook() {
    33.         return new SamsMySQLBook;// метод создания книги о MySQL
    34.     }
    35. }
    36.  
    37.  
    38. // далее класс книг (продукты)
    39.  
    40.  
    41. // абстрактная книга
    42. abstract class AbstractBook {
    43.     abstract function getAuthor();
    44.     abstract function getTitle();
    45. }
    46.  
    47.  
    48. // абстрактная книга по MYSQL
    49. abstract class AbstractMySQLBook extends AbstractBook {
    50.     private $subject = "MySQL";
    51. }
    52.  
    53. //  книга по MYSQL от издательства О'РЕйли
    54. class OReillyMySQLBook extends AbstractMySQLBook {
    55.     private $author;
    56.     private $title;
    57.     function __construct() {
    58.         $this->author = 'George Reese, Randy Jay Yarger, and Tim King';
    59.         $this->title = 'Managing and Using MySQL';
    60.     }
    61.     function getAuthor() {
    62.         return $this->author;
    63.     }
    64.     function getTitle() {
    65.         return $this->title;
    66.     }
    67. }
    68.  
    69. //  книга по MYSQL от издательства Самс
    70. class SamsMySQLBook extends AbstractMySQLBook {
    71.     private $author;
    72.     private $title;
    73.     function __construct() {
    74.         $this->author = 'Paul Dubois';
    75.         $this->title = 'MySQL, 3rd Edition';
    76.     }
    77.     function getAuthor() {
    78.         return $this->author;
    79.     }
    80.     function getTitle() {
    81.         return $this->title;
    82.     }
    83. }
    84.  
    85.  
    86. //  абстрактная книга по PHP
    87. abstract class AbstractPHPBook extends AbstractBook{
    88.     private $subject = "PHP";
    89. }
    90.  
    91. //  конкретная книга по PHP от издательства О'РЕйли
    92. class OReillyPHPBook extends AbstractPHPBook {
    93.     private $author;
    94.     private $title;
    95.     private static $oddOrEven = 'odd';
    96.     function __construct()
    97.     {
    98.         //выбираем между двумя книгами
    99.         if ('odd' == self::$oddOrEven) {
    100.             $this->author = 'Rasmus Lerdorf and Kevin Tatroe';
    101.             $this->title = 'Programming PHP';
    102.             self::$oddOrEven = 'even';
    103.         }
    104.         else {
    105.             $this->author = 'David Sklar and Adam Trachtenberg';
    106.             $this->title = 'PHP Cookbook';
    107.             self::$oddOrEven = 'odd';
    108.         }
    109.     }
    110.     function getAuthor() {
    111.         return $this->author;
    112.     }
    113.     function getTitle() {
    114.         return $this->title;
    115.     }
    116. }
    117.  
    118.  
    119. //  конкретная книга по PHP от издательства Самс
    120. class SamsPHPBook extends AbstractPHPBook {
    121.     private $author;
    122.     private $title;
    123.     function __construct() {
    124.         //случайным образом выбираем одну книгу из двух
    125.         mt_srand((double)microtime() * 10000000);
    126.         $rand_num = mt_rand(0, 1);
    127.         if (1 > $rand_num) {
    128.             $this->author = 'George Schlossnagle';
    129.             $this->title = 'Advanced PHP Programming';
    130.         }
    131.         else {
    132.             $this->author = 'Christian Wenz';
    133.             $this->title = 'PHP Phrasebook';
    134.         }
    135.     }
    136.     function getAuthor() {
    137.         return $this->author;
    138.     }
    139.     function getTitle() {
    140.         return $this->title;
    141.     }
    142. }
    143.  
    144.  
    145.  
    146.  
    147.  
    148.  
    149. writeln('<br><b>тестируем работу конкретной фабрики  издательства OReilly</b><br>');
    150. $bookFactoryInstance = new OReillyBookFactory; // создаём экземпляр фабрики
    151.  
    152. // запускаем функцию тестирования передав в неё в качестве параметра
    153. // экземпляр нашей фабрики
    154. testConcreteFactory($bookFactoryInstance); // запустили тестирование
    155.  
    156.  
    157. writeln('<br><b>тестируем работу конкретной фабрики  издательства Sams</b><br>');
    158. $bookFactoryInstance = new SamsBookFactory; // создаём экземпляр фабрики
    159. testConcreteFactory($bookFactoryInstance); // запустили тестирование
    160.  
    161.  
    162.  
    163. /*
    164. далее приводим код самой функции тестирование - она-то
    165. как раз и демонстрирует "удобство" применения паттерна Абстрактная фабрика
    166. */
    167. function testConcreteFactory($bookFactoryInstance) // принимает объект конретной фабрики
    168. {
    169.     // вызываем  метод создания PHP книги - наш код не зависит от того какое именно издательство
    170.     // передано (фабрика какого именно издательства передана) для реализации создания книг  
    171.     $phpBookOne = $bookFactoryInstance->makePHPBook();
    172.     writeln('Автор первой книги  по PHP: '.$phpBookOne->getAuthor());
    173.     writeln('Заголовок первой книги  по PHP: '.$phpBookOne->getTitle());
    174.  
    175.     $phpBookTwo = $bookFactoryInstance->makePHPBook();
    176.     writeln('Автор второй книги по PHP: '.$phpBookTwo->getAuthor());
    177.     writeln('Заголовок второй книги по PHP:: '.$phpBookTwo->getTitle());
    178.  
    179.     $mySqlBook = $bookFactoryInstance->makeMySQLBook();
    180.     writeln('Автор  книги по MySQL: '.$mySqlBook->getAuthor());
    181.     writeln(' Заголовок книги по MySQL: '.$mySqlBook->getTitle());
    182. }
    183.  
    184. function writeln($line_in) {
    185.     echo $line_in."<br/>";
    186. }
    187. ?>

    вопрос, объясните, что тут происходит:


    PHP:
    1. function __construct()
    2.     {
    3.         //выбираем между двумя книгами
    4.         if ('odd' == self::$oddOrEven) {
    5.             $this->author = 'Rasmus Lerdorf and Kevin Tatroe';
    6.             $this->title = 'Programming PHP';
    7.             self::$oddOrEven = 'even';
    8.         }
    9.         else {
    10.             $this->author = 'David Sklar and Adam Trachtenberg';
    11.             $this->title = 'PHP Cookbook';
    12.             self::$oddOrEven = 'odd';
    13.         }
    14.     }
    для чего нам $oddOrEven и что такое odd и even (строки)
     
    Алекс8 нравится это.
  12. Алекс8

    Алекс8 Активный пользователь

    С нами с:
    18 май 2017
    Сообщения:
    1.730
    Симпатии:
    359
    ну по ходу при создании объекта всегда будет условие odd выбираться.. зачем там else не понятно..
     
  13. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.555
    Симпатии:
    1.754
    Ну это они так чередуют просто, чтоб OReillyPHPBook то одно название, то другое выдавал. Это не часть паттерна, это просто люди попытались придумать короткий пример абстрактной фабрики, что очень непросто, поскольку это паттерн для решения сложных задач. Видно же, как они используют если odd, то автор Rasmus Lerdorf and Kevin Tatroe и меняется на even. Вы совсем код не читаете, такую элементарную вещь не видите?

    Сам паттерн здесь в том, что одна фабрика даёт книги по php и mysql от O'Reily, другая от Sams. Тут правда в примере главное не показано - какую из двух фабрик использовать, можно решить в процессе выполнения скрипта, на основе когфига или пользовательского ввода. Видите, у них testConcreteFactory() не знает, с какой она фабрикой работает, можно передать и орайли, и самс - она только знает, что реализует интерфейс AbstractBookFactory - ну это полиморфизм в действии. Если полиморфизм не понимаете, то паттерны вам рано, они все его так или иначе используют, и вообще, это единственная причина использовать ООП. Если не нужен полиморфизм, не нужно и ООП.
    --- Добавлено ---
    Любой короткий пример будет искусственным. Вот в книге, которую я рекомендую, там более-менее похожий на реал пример, но там страницы 4 о нём, я их сюда перепечатывать не буду.
     
    Алекс8 нравится это.
  14. artemka

    artemka Новичок

    С нами с:
    18 авг 2017
    Сообщения:
    56
    Симпатии:
    4
    ну по сути пример же описывает эту фабрику...
     
  15. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.555
    Симпатии:
    1.754
    Вот суть абстрактной фабрики. Всё. Теперь ты можешь сколько угодно создавать разных фабрик книг про php и mysql, функция testConcreteFactory будет работать с любой. То, на чём ты споткнулся почему-то, это уже конкретная реализация класса книги, объекты которых должны создавать фабрики, и она не важна. Но ты всё примеры только смотришь, теорию не хочешь рассматривать, я так понимаю. С ООП так не выйдет. За ООП стоит большой и сложный теоретический аппарат, в одном посте не опишешь. Я тебе дал название книги и ссылку на лекции, по которым это осваивал я. Почитай. Да, мой код улучшился после знакомства с этими материалами. Хотя не скажу, что у меня вот в каждом проекте куча абстрактных фабрик (или вообще фабрик). Паттерны изучаются не для того, чтобы пихать их везде, Короткий рабочий пример абстрактной фабрики, где она давала бы хоть какой-то смысл, ты не найдёшь. Увы. Если у тебя в проекте потребовалась абстрактная фабрика, значит он уже относительно крупный.
    --- Добавлено ---
    Один из базовых принципов ООП - интерфейс важнее реализации.
     
    Алекс8 и artemka нравится это.
  16. artemka

    artemka Новичок

    С нами с:
    18 авг 2017
    Сообщения:
    56
    Симпатии:
    4
    спасибо большое, помогли
     
  17. Алекс8

    Алекс8 Активный пользователь

    С нами с:
    18 май 2017
    Сообщения:
    1.730
    Симпатии:
    359
    я наверно совсем торможу)) но odd и even вижу только в конструкторе используется.. более того $oddOrEven это даже не параметр конструктора, а приватное свойство.. значит при создании объекта мы никак не можем его поменять..
    или просто этот код воспринимать как пример а не как что то рабочее))?
    Спасибо)
     
  18. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.555
    Симпатии:
    1.754
    @Алекс8, оно статическое, т.е. общее для всех экземпляров классов, и каждый вызов конструктора его переключает с odd на even и обратно. См. строки 7 и 12 листинга, где конструктор отдельно.
    --- Добавлено ---
    Пример искусственный, но рабочий вроде.
     
    Алекс8 нравится это.
  19. Алекс8

    Алекс8 Активный пользователь

    С нами с:
    18 май 2017
    Сообщения:
    1.730
    Симпатии:
    359
    ооо.. я слепошара.. действительно статик.. а я на private глянул а дальше пропустил))
    спасибо большое))
     
  20. artemka

    artemka Новичок

    С нами с:
    18 авг 2017
    Сообщения:
    56
    Симпатии:
    4
    я сделал рандомно, как ниже в классе.
     
  21. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.555
    Симпатии:
    1.754
    Хоть понял, нафига это всё придумали?
     
  22. artemka

    artemka Новичок

    С нами с:
    18 авг 2017
    Сообщения:
    56
    Симпатии:
    4
    +-))) я книг вашу нашел, буду читать