首页 > 技术文章 > 设计模式

zhang-zi-yi 2019-04-22 12:58 原文

设计模式

接口:

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

    • 作用:

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

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

  • python 中的接口实现

    from abc import abstractmethod, ABCMeta
    
    class InterFace(metaclass=ABCMeta):
        @abstractmethod
        def method(self):
            pass
        
        def method1(self):
            raise NotImplementedError
    
    class Asd(InterFace):
        # 必须重写父类的  method  方法 
        pass
    
    Asd()
    

设计模式六大原则:

  1. 开闭原则

    一个软件实体如类,模块和函数应该对扩展开放, 对修改关闭. 即软件实体尽量在不修改原有代码的情况下进行扩展

  2. 里氏 (Liskov) 替换原则

    所有引用基类的地方必须能透明的 使用其子类的对象.

  3. 依赖倒置原则

    高层模块不应该依赖底层模块,二者都应该依赖其抽象; 抽象不应该依赖细节;细节应该依赖抽象.

    要针对接口编程, 而不是针对实现编程

  4. 接口隔离原则

    使用多个专门的接口,而不是用其单一的总接口,即客户端不应该依赖那些它不需要的接口

  5. 迪米特法则

    一然见实体应当尽可能少的与其他实体发生相互作用

  6. 单一职责原则

    不要存在多于一个导致类变更的原因,

    即一个类只负责一项职责

单例模式

  • 保证一个类只有一个实例,并提供一个访问它的全局访问点
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")
b = MyClass("b")
c = MyClass("c")
print(a.name)  # c
print(b.name)  # c
print(c.name)  # c

简单工厂模式

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

  • 角色:

    工厂角色(Creator)

    抽象产品角色(Product)

    具体产品角色(Concrete Product)

  • 优点:

    隐藏了对象创建的实现细节

    客户端不需要修改代码

  • 缺点:

    违反了单一职责原则,将创建逻辑几种到一个工厂类里

    当添加新产品时,需要修改工厂类代码,违反了开闭原则

# coding : utf-8

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()
        elif method == 'huabei':
            return Alipay(use_huabei=True)
        elif method == "applepay":
            return ApplePay()
        else:
            raise NameError(method)


# 傻子程序员

pf = PaymentFactory()
p = pf.create_payment("huabei")
p.pay(100)

工厂方法模式

  • 适用场景:

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

    需要降低耦合度的时候

    当系统中的产品种类需要经常扩展的时候

  • 优点:

    每个具体产品都对应一个具体工厂类,不需要修改工厂类代码

    隐藏了对象创建的实现细节

  • 缺点:

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

# coding : utf-8
# create by ztypl on 2017/5/25

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(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()




# 用户输入
# 支付宝,120

af = HuabeiFactory()
ali = af.create_payment()
ali.pay(120)

抽象工厂模式

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

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

  • 角色:

    n抽象工厂角色(Creator)

    n具体工厂角色(Concrete Creator)

    n抽象产品角色(Product)

    n具体产品角色(Concrete Product)

    n客户端(Client)

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

# coding : utf-8
# create by ztypl on 2017/5/25

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()

适配器模式

# coding : utf-8
# create by ztypl on 2017/5/25

from abc import abstractmethod, ABCMeta

# A

class Payment(metaclass=ABCMeta):
    @abstractmethod
    def pay(self, money):
        raise NotImplementedError


class Alipay(Payment):
    def pay(self, money):
        print("支付宝支付%s元"%money)


class ApplePay(Payment):
    def pay(self, money):
        print("苹果支付%s元"%money)

#------待适配类------

# B

class WechatPay:
    def huaqian(self, money):
        print("微信支付%s元"%money)


class BankPay:
    def huaqian(self, money):
        print("银行卡支付%s元"%money)


# 适配器

# 类适配器

# class RealWechatPay(Payment, WechatPay):
#     def pay(self, money):
#         self.huaqian(money)

# 复用代码: 继承 组合

# class A:
#     pass
#
# class C:
#     pass
#
# class B:
#     def __init__(self):
#         self.a = A()
#         self.c = C()

# 对象适配器

class PaymentAdapter(Payment):
    def __init__(self, bad_payment):
        self.p = bad_payment()

    def pay(self, money):
        self.p.huaqian(money)


p = PaymentAdapter(WechatPay)
p.pay(100)

代理模式

# coding : utf-8
# create by ztypl on 2017/5/26

from abc import ABCMeta, abstractmethod


class Subject(metaclass=ABCMeta):
    @abstractmethod
    def get_content(self):
        pass

    @abstractmethod
    def set_content(self):
        pass


class RealSubject(Subject):
    def __init__(self, filename):
        print("读取%s文件内容"%filename)
        f = open(filename)
        self.content = f.read()
        f.close()

    def get_content(self):
        return self.content

    def set_content(self):
        pass


# 虚代理

class ProxyB(Subject):
    def __init__(self, filename):
        self.filename = filename
        self.subj = None

    def get_content(self):
        if not self.subj:
            self.subj = RealSubject(self.filename)
        return self.subj.get_content()


obj = ProxyB('abc.txt')
print(obj.get_content())



class ProxyC(Subject):
    def __init__(self, filename):
        self.subj = RealSubject(filename)

    def get_content(self):
        return self.subj.get_content()

    def set_content(self):
        raise PermissionError

责任链模式

观察者模式

策略模式

人工智能论坛

www.aboutyun.com

推荐阅读