Описание

Описание

Даниил Дмитриевич

## На чем это все написано?


C# + Avalonia + MVVM Pattern


---


## Про сам паттерн


#### Объяснение для преподавателя:


Паттерн "Абстрактная фабрика" (Abstract Factory) относится к паттернам создания (Creational Patterns) и предоставляет интерфейс для создания семейств взаимосвязанных объектов, не указывая их конкретных классов.


Основные составляющие паттерна "Абстрактная фабрика":


1. Абстрактная фабрика (Abstract Factory): определяет интерфейс для создания семейств связанных объектов. Обычно содержит абстрактные методы для создания каждого объекта в семействе.


2. Конкретная фабрика (Concrete Factory): реализует абстрактную фабрику и создает конкретные объекты семейства.


3. Абстрактный продукт (Abstract Product): определяет интерфейс для продукта, который будет создан фабрикой.


4. Конкретный продукт (Concrete Product): реализует абстрактный продукт и представляет конкретный объект, который будет создан фабрикой.


5. Клиент (Client): использует абстрактную фабрику и продукты, созданные ею. Клиент не зависит от конкретных классов продуктов, он работает только с абстрактными интерфейсами.


Паттерн "Абстрактная фабрика" позволяет создавать семейства объектов, которые взаимодействуют друг с другом и должны быть созданы вместе. Он обеспечивает гибкость и изолирует клиентский код от конкретных классов продуктов, позволяя легко заменять семейства продуктов без изменения клиентского кода.


---


#### Нормальное объяснение:


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


Собственно решение: нам нужно инкапсулировать процесс создания нового объекта. Не совсем понятно, да? Короче, нам нужно скрыть от глаз создания объекта. Мы просто должны сказать: "Хочу вот это" и все, программа должна сделать объект сама по заданным ранее условиям.


Что для этого надо?

Нам нужна одна абстрактная фабрика, в которой мы зададим методы для создания объектов. Далее в настоящих (не абстрактных, а реальных фабриках) мы прописываем создания обьекта, то есть заполняем в самом простом случае большой конструктор.

Так же у нас должен быть базовый обьект (продукт) для создания и от него отходят реальные продукты, которые, разумеется, следуя логике наследования, могут содержать разные поля.


Рассмотрим на нашем примере.

У нас есть базовый или же абстрактный предмет - Electronics.


```csharp

public abstract class Electronics

   {

       private double _price;

       private int _powerConsumprion;

       

       public string Brand { get; set; }


       public string Model { get; set; }

       

       public double Price

       {

           get

           {

               return _price;

           }

           set

           {

               if (value <= 0)

               {

                   throw new ArgumentException();

               }


               _price = value;

           }

       }


       public int PowerConsumprion

       {

           get

           {

               return _powerConsumprion;

           }

           set

           {

               if (value <= 0)

               {

                   throw new ArgumentException();

               }


               _powerConsumprion = value;

           }

       }


       public Electronics(string brand, string model, double price, int powerConsumption)

       {

           Brand = brand;

           Model = model;

           Price = price;

           PowerConsumprion = powerConsumption;

       }

   }

```


В нем мы определили базовые свойства, а уже потом от этого класса наследуем другие, такие как `Laptop`, `Smartphone`, `TV`. В каждом классе есть что-то свое характерное.


Далее мы создаем абстрактную фабрику.

```csharp

public abstract class ElectonicsFactory

   {

       public abstract Electronics.Electronics CreateLaptop();


       public abstract Electronics.Electronics CreateSmartphone();


       public abstract Electronics.Electronics CreateTV();

   }

```


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


Вот так делает наши товары фабрика Apple:

```csharp

public class AppleFactory : ElectonicsFactory

   {

       public override Electronics.Electronics CreateLaptop()

       {

           return new Laptop("Apple",

               "Macbook",

               1000,

               85,

               "M1",

               13.5,

               DisplayType.IPS,

               512);

       }


       public override Electronics.Electronics CreateSmartphone()

       {

           return new Smartphone("Apple",

               "iPhone",

               800,

               15,

               7.5,

               12,

               DisplayType.Oled,

               OperationSystemType.IOS);

       }


       public override Electronics.Electronics CreateTV()

       {

           return new TV("Apple",

               "HomeTV",

               1200,

               120,

               DisplayType.IPS,

               55,

               true);

       }

   }


```


А вот так, уже иначе, делает это Samsung:

```csharp

public class SamsungFactory : ElectonicsFactory

   {

       public override Electronics.Electronics CreateLaptop()

       {

           return new Laptop("Samsung",

               "Galaxy Book",

               750,

               85,

               "Intel Core i7",

               14.5,

               DisplayType.IPS,

               256);

       }


       public override Electronics.Electronics CreateSmartphone()

       {

           return new Smartphone("Samsung",

               "Galaxy 7",

               470,

               15,

               7.5,

               16,

               DisplayType.Oled,

               OperationSystemType.Android);

       }


       public override Electronics.Electronics CreateTV()

       {

           return new TV("Samsung",

               "SmartTV",

               1200,

               120,

               DisplayType.IPS,

               55,

               true);

       }

   }

```


Но нам в любом случае это не интересно, мы просто закажем у одной из этой фабрик телефон или ноутбук и все.


Другой пример из жизни.

В играх часто есть однотипные мобы. Допустим, это будут зомби. Неужели разработчик каждый раз прописывает для одинаковых зомби один и тот же процесс создания? Нет, однозначно нет. Что сделает грамотный разработчик? Он создаст фабрику, которая будет за него делать этих несчастных зомби. А что если он захочет еще и делать злых крыс? Добавим процесс создания крыс в нашу фабрику. Теперь не надо париться над созданием, просто: "Эй, фабрика, сделай мне парочку зомби и 5 крыс".


Ага, круто, но что если мы захотим делать более злых, страшных зомби и крыс? Надо создать новую фабрику и в ней по-другому прописать создание таких объектов, вот и все дела. Новый уровень - новая фабрика по созданию мобов. Так же можно использовать несколько фабрик.


---


## Структура проекта


- `Assets` - ресурсы проекта (изображения)

- `Models` - модели (данные)

   - `Electronics` - модели электроники (товары)

      - `Electronics` - абстрактный класс продукта (базовый для дальнейшего наследования)

      - `Laptop`

      - `Smartphone`

      - `TV`

   - `Factories`

      - `ElectronicsFactory` - абстрактный класс фабрики (базовый для дальнейшего наследования)

      - `AppleFactory`

      - `SamsungFactory`

      - `SonyFactory`

   - `Interfaces`

      - `IHaveOperaionSystem` - интерфейс для тех, у кого есть операционная систем

      - `IHaveScreen` - интерфейс для тех, у кого есть экран

   - `Types`

      - `DisplayType` - типы экранов

      - `OperationSystemType` - типы операционных систем

- `ViewModels` - клей между данными и отображением

   - `ElectonicsViewModel` - данные для отображения типа продукта (телефон, ТВ, ноутбук)

   - `FactoryViewModel` - данные для отображения типа производителя

   - `MainViewModel` - главное окно, в ней реализована логика перехода по страницам, логика создания при выборе

   - `ModelPageViewModel` - данные для отображения созданного продукта

   - `SelectElectronicsPageViewModel` - данные для отображения выбора продукта

   - `SelectFactoryPageViewModel` - данные для отображения выбора производителя

   - `ViewModelBase`

- `Views` - отображение

   - `MainWindow`

   - `ModelPageView`

   - `SelectElectronicsPageView`

   - `SelectFactoryPageView`


## Замечания от автора


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

- Интерфейсы и типы были лишь созданы для демонстрации навыков программирования для преподавателя




- Лучший способ отблагодарить программиста (помимо чаевых, разумеется) - сделать новый заказ и оставить хороший отзыв. Спасибо!

Report Page