设计模式

十年热恋 提交于 2020-02-29 18:41:53

一.python中的对象(类)和接口

1.对象/类

三大特征: 封装, 继承, 多态

封装: 将方法封装或属性到一个类中

继承: 子类可以继承父类的方法和属性

多态: python动态语言, 天生就是多态的, python中没有非多态的方法. 所以不用考虑python中的多态具体是如何体现出来的

2.接口

概述: 接口是一种特殊的类, 该类中声明了若干方法, 要求继承了该接口的类必须实现这些方法.

作用: 限制继承接口的 类的 方法名称和调用方式; 隐藏了类的内部实现.

接口就是一种抽象的基类(父类), 限制继承它的类必须实现接口中定义的某些方法.

3.python中接口的两种写法

写法一

class Interface:
    def method(self, arg):
        raise NotImplementedError

写法二

from abc import abstractmethod, ABCMeta

class Interface(metaclass=ABCMeta):
    @abstractmethod
    def method(self, arg):
        pass

二.设计模式六大原则

开闭原则: 一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。

里氏替换原则: 所有引用基类(父类)的地方必须能透明地使用其子类的对象。

依赖倒置原则: 要针对接口编程,而不是针对实现编程。

接口隔离原则: 一个接口对应一个功能

, 即不要把多个功能放到一个接口中去。

迪米特法则: 实体与实体之间的耦合度应尽可能低。

单一职责原则: 一个类只负责一项职责。

三.设计模式分类

1.简单工厂模式

内容: 不直接向客户端暴露对象创建的实现细节,而是而是通过一个工厂类来负责创建产品类的实例。

角色:

  • 工厂角色(Creator)

  • 抽象产品角色(Product)

  • 具体产品角色(Concrete Product)

优点:

  • 隐藏了对象创建的实现细节
  • 客户端不需要修改代码

缺点:

  • 违反了单一职责原则,将创建逻辑集中到一个工厂类里
  • 当添加新产品时,需要修改工厂类代码,违反了开闭原则

实例:

from abc import abstractmethod, ABCMeta

# 抽象产品角色
class Payment(metaclass=ABCMeta):
    @abstractmethod
    def pay(self, money):
        raise NotImplementedError

# 具体产品角色
class AliPay(Payment):
    def __init__(self, use_huabei):
        self.use_huabei = use_huabei
        
    def pay(self, money):
        if self.use_huabei:
            print('花呗支付%s元' % money)
        else:
            print('支付宝支付%s元' % money)

# 具体产品角色
class ApplePay(Payment):
    def pay(self, money):
        print('苹果支付%s元' % money)

# 工厂角色
class PaymentFactory:
    def create_payment(self, method):
        if method == 'alipay':
            return AliPay(use_huabei=False)
        elif method == 'huabei':
            return AliPay(use_huabei=True)
        elif method == 'applepay':
            return ApplePay()

# 实例化工厂角色
pf = PaymentFactory()
# 工厂 实例化一个 具体产品角色
p = pf.create_payment('alipay')
p.apy(100)

2.工厂方法模式

内容: 定义一个用于创建对象的接口(工厂接口),让子类决定实例化哪一个产品类。

角色:

  • 抽象工厂角色(Creator)

  • 具体工厂角色(Concrete Creator)

  • 抽象产品角色(Product)
  • 具体产品角色(Concrete Product)

工厂方法模式相比简单工厂模式将每个具体产品都对应了一个具体工厂。

适用场景:

  • 需要生产多种、大量复杂对象的时候

  • 需要降低耦合度的时候
  • 当系统中的产品种类需要经常扩展的时候

优点:

  • 每个具体产品都对应一个具体工厂类,不需要修改工厂类代码
  • 隐藏了对象创建的实现细节

缺点: 每增加一个具体产品类,就必须增加一个相应的具体工厂类

实例:

from abc import abstractmethod, ABCMeta

# 抽象产品角色
class Payment(metaclass=ABCMeta):
    @abstractmethod
    def pay(self, money):
        raise NotImplementedError

# 具体产品角色
class AliPay(Payment):
    def __init__(self, use_huabei=False):
        self.use_huabei = use_huabei
        
    def pay(self, money):
        if self.use_huabei:
            print('花呗支付%s元' % money)
        else:
            print('支付宝支付%s元' % money)

# 具体产品角色
class ApplePay(Patment):
    def pay(self, money):
        print('苹果支付%s元' % money)

# 抽象工厂角色
class PaymentFactory(metaclass=ABCMeta):
    @abstractmethod
    def create_payment(self):
        pass

# 具体工厂角色
class AlipayFactory(PaymentFactory):
    def create_payment(self):
        return Alipay()

# 具体工厂角色
class HuabeiFactory(PaymentFactory):
    def create_payment(self):
        return Alipay(use_huabei=True)

# 具体工厂角色
class ApplePayFactory(PaymentFactory):
    def create_payment(self):
        return ApplePay()

# 实例化一个具体工厂角色
hf = HuabeiFactory()
# 使用具体工厂 实例化一个 具体产品
huabei = hf.create_payment()
huabei.pay(120)

3.抽象工厂模式

内容: 定义一个工厂类接口,让工厂子类来创建一系列相关或相互依赖的对象。

例:生产一部手机,需要手机壳、CPU、操作系统三类对象进行组装,其中每类对象都有不同的种类。对每个具体工厂,分别生产一部手机所需要的三个对象。

角色:

  • 抽象工厂角色(Creator)

  • 具体工厂角色(Concrete Creator)

  • 抽象产品角色(Product)
  • 具体产品角色(Concrete Product)

  • 客户端(Client)

相比工厂方法模式,抽象工厂模式中的每个具体工厂都生产一套产品。

适用场景:

  • 系统独立于产品的创建与组合时
  • 强调一系列相关的产品对象的设计以便进行联合使用时
  • 提供一个产品类库,想隐藏产品的具体实现时

优点:

  • 将客户端与类的具体实现相分离
  • 每个工厂创建了一个完整的产品系列,使得易于交换产品系列
  • 有利于产品的一致性(即产品之间的约束关系)

缺点:

  • 难以支持新种类的(抽象)产品
from abc import abstractmethod, ABCMeta


# ------抽象产品------

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("苹果手机壳")


class SnapDragonCPU(CPU):
    def show_cpu(self):
        print("骁龙CPU")


class MediaTekCPU(CPU):
    def show_cpu(self):
        print("联发科CPU")


class AppleCPU(CPU):
    def show_cpu(self):
        print("苹果CPU")


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):
    cpu = factory.make_cpu()
    os = factory.make_os()
    shell = factory.make_shell()
    return Phone(cpu, os, shell)


p1 = make_phone(IPhoneFactory())
p1.show_info()

4.单例模式

内容: 保证一个类只有一个实例,并提供一个访问它的全局访问点。

角色:单例(Singleton)

适用场景: 当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。

优点:

  • 对唯一实例的受控访问
  • 单例相当于全局变量,但防止了命名空间被污染

与单例模式功能相似的概念:全局变量、静态变量(方法)

实例:

class Singleton(object):
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, "_instance"):
            cls._instance = super(Singleton, cls).__new__(cls)
        return cls._instance


class MyClass(Singleton):
    def __init__(self, name=None):
        if name is not None:
            self.name = name


a = MyClass("a")
#print(a)
print(a.name)
b = MyClass("b")
#print(b)
print(b.name)
#print(a)
print(a.name)

5.创建型模式小结

  • 依赖于继承的创建型模式:工厂方法模式
  • 依赖于组合的创建性模式:抽象工厂模式、创建者模式

6.适配器模式

待续

7.代理模式

待续

8.责任链模式

待续

9.观察者模式

待续

10.策略模式

待续

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!