#! /usr/bin/env python
# -*- coding: utf-8 -*-

from abc import abstractmethod, ABCMeta

"""
Преимущества: 
     1. Отделение клиента от конкретной реализации класса
     2. Каждая фабрика создает полную линейку продуктов
     3. Способствует согласованности продукта
Недостатки:
     Сложно поддерживать новые типы (абстрактных) продуктов
"""


# ------Абстрактный продукт------
class PhoneShell(metaclass=ABCMeta):
    @abstractmethod
    def show_shell(self):
        pass


class CPU(metaclass=ABCMeta):
    @abstractmethod
    def show_cpu(self):
        pass


class OS(metaclass=ABCMeta):
    @abstractmethod
    def show_os(self):
        pass


# ------Абстрактная фабрика------
class PhoneFactory(metaclass=ABCMeta):
    @abstractmethod
    def make_shell(self):
        pass

    @abstractmethod
    def make_cpu(self):
        pass

    @abstractmethod
    def make_os(self):
        pass


# ------Конкретный продукт------
class SmallShell(PhoneShell):
    def show_shell(self):
        print("Обычный мобильный телефон маленький чехол для мобильного телефона")


class BigShell(PhoneShell):
    def show_shell(self):
        print("Обычный чехол для мобильного телефона")


class AppleShell(PhoneShell):
    def show_shell(self):
        print("Чехол для телефона Apple")


class SnapDragonCPU(CPU):
    def show_cpu(self):
        print("Snapdragon CPU")


class MediaTekCPU(CPU):
    def show_cpu(self):
        print("MediaTek CPU")


class AppleCPU(CPU):
    def show_cpu(self):
        print("Процессор Apple")


class Android(OS):
    def show_os(self):
        print("Android")


class IOS(OS):
    def show_os(self):
        print("система iOS")


class MiFactory(PhoneFactory):
    def make_cpu(self):
        return SnapDragonCPU()

    def make_os(self):
        return Android()

    def make_shell(self):
        return BigShell()


class HuaweiFactory(PhoneFactory):
    def make_cpu(self):
        return MediaTekCPU()

    def make_os(self):
        return Android()

    def make_shell(self):
        return SmallShell()


class IPhoneFactory(PhoneFactory):
    def make_cpu(self):
        return AppleCPU()

    def make_os(self):
        return IOS()

    def make_shell(self):
        return AppleShell()


# ------Клиент------
class Phone:
    def __init__(self, cpu, os, shell):
        self.cpu = cpu
        self.os = os
        self.shell = shell

    def show_info(self):
        print("Информация о мобильном телефоне:")
        self.cpu.show_cpu()
        self.os.show_os()
        self.shell.show_shell()


def make_phone(factory: PhoneFactory) -> Phone:
    cpu = factory.make_cpu()
    os = factory.make_os()
    shell = factory.make_shell()
    return Phone(cpu, os, shell)


p1 = make_phone(HuaweiFactory())
p1.show_info()
