面向对象设计原则和模式

面向对象设计原则

开放封闭原则:

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

里氏替换原则:

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

依赖倒置原则:

  高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象;即针对接口编程,而不是针对实现编程

工厂方法模式

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

角色:

  抽象工厂角色(creator)

  具体工厂角色(concrete creator)

  抽象产品角色(product)

  具体产品角色(concrete product)

例子:比如我们有一个染色的机器,我们要给指定的机器生产对应的工艺编程

from abc import ABCMeta, abstractmethod
#抽象产品
class CraftProgramming(metaclass=ABCMeta):
    #abstract class
    @abstractmethod
    def setStep(self,step: list):
        pass
#具体产品
class ModelTypeACraft(CraftProgramming):
    def __init__(self,childModelType=False):
        self.childModelType =childModelType
    def setStep(self,step: list):
        if self.childModelType:
            print(f"A机型-{self.childModelType}工艺工步为{step}")
        else:
            print(f"A机型工艺工步为{step}")

class ModelTypeBCraft(CraftProgramming):
    def setStep(self,step: list):
            print(f"B机型工艺工步为{step}")
#抽象工厂
class CraftProgrammingFactory(metaclass=ABCMeta):
    @abstractmethod
    def creatCraft(self):
        pass
#具体工厂
class ModelTypeACraftFactory(CraftProgrammingFactory):
    def creatCraft(self):
        return ModelTypeACraft()

class ModelTypeBCraftFactory(CraftProgrammingFactory):
    def creatCraft(self):
        return ModelTypeBCraft()

class ModelTypeAChildCraftFactory(CraftProgrammingFactory):
    def creatCraft(self):
        return ModelTypeACraft(childModelType=True)

cf = ModelTypeACraftFactory()
c = cf.creatCraft()
c.setStep([])

 优点:

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

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

缺点:

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

抽象工厂模式

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

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

例子:我们延续上面的染色机工艺编程的例子,一个工艺我们分为工步、参数、工步类型

from abc import ABCMeta, abstractmethod
#抽象产品
class CraftParameter(metaclass=ABCMeta):
    #abstract class
    @abstractmethod
    def setParameter(self):
        pass

class CraftStep(metaclass=ABCMeta):
    #abstract class
    @abstractmethod
    def setStep(self,step: list):
        pass

class CraftFuntionType(metaclass=ABCMeta):
    #abstract class
    @abstractmethod
    def setFuntionType(self,funcType: int):
        pass

#抽象工厂
class CreatCraftFactory(metaclass=ABCMeta):
    @abstractmethod
    def creatParameter(self):
        pass

    @abstractmethod
    def creatStep(self):
        pass

    @abstractmethod
    def creatFuntionType(self):
        pass

#具体产品
class ModelTypeACraftParameter(CraftParameter):
    def setParameter(self):
        print("A机型工艺的参数")

class ModelTypeACraftStep(CraftStep):
    def setStep(self,step: list):
        print(f"A机型工艺的工步{step}")

class ModelTypeACraftFuntionType(CraftFuntionType):
    def setFuntionType(self,funcType: int):
        print(f"A机型工艺的工步类型{funcType}")

#具体工厂
class ModelTypeACreatCraftFactory(CreatCraftFactory):
    def creatParameter(self):
        return ModelTypeACraftParameter()

    def creatStep(self):
        return ModelTypeACraftStep()

    def creatFuntionType(self):
        return ModelTypeACraftFuntionType()

#客户端
class Craft:
    def __init__(self,parameter,step,funtionType):
        self.parameter = parameter
        self.step = step
        self.funtionType = funtionType

    def craft_info(self):
        self.parameter.setParameter()
        self.step.setStep([])
        self.funtionType.setFuntionType(1)

def creatCraft(factory):
    parameter = factory.creatParameter()
    step = factory.creatStep()
    funtionType = factory.creatFuntionType()
    return Craft(parameter,step,funtionType)

c1 = creatCraft(ModelTypeACreatCraftFactory())
c1.craft_info()

优点:

  客户端与类具体实现分离

  每个工厂都有一个完成的产品系列,易于交换产品系列和产品一致性

缺点:

  难以支持新的抽象产品

单例模式

定义:保证一个类只有一个实例,并提供一个访问他的全局访问点

角色:singleton

优点:

  对唯一实例受控访问

  单例相当于全局变量,防止命名空间被污染

  常用于日志、数据库等

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

class MyClass(Singleton):
    def __init__(self,a):
        self.a = a

a=MyClass(10)

b=MyClass(20)

print(a.a) #20
print(b.a) #20
print(id(a) , id(b)) #id相同

 适配器模式

定义:将一个类接口转换成客户希望的另一个接口。适配器使得原来接口不兼容的现在可以一起工作

类适配器:使用类的继承

对象适配器:使用组合

from abc import ABCMeta, abstractmethod

class CraftParameter(metaclass=ABCMeta):
    #abstract class
    @abstractmethod
    def setParameter(self):
        pass

class ModelACraftParameter(CraftParameter):
    def setParameter(self):
        print("A机型的工艺参数")

class ModelBCraftParameter(CraftParameter):
    def setParameter(self):
        print("B机型的工艺参数")

class ModelCCraftParameter:
    def insertParameter(self):
        print("C机型的工艺参数")

#这个时候我们发现C机型方法和A、B机型的方法不一致,我们需要去适配C机型
#第一种方法:类适配器
class NewModelCraftParameter(CraftParameter,ModelCCraftParameter):
    def setParameter(self):
        self.insertParameter()

#第二种办法:对象适配器
class CraftParameterAdapter:
    def __init__(self,craftParameter):
        self.craftParameter = craftParameter

    def setParameter(self):
        self.craftParameter().insertParameter()

# c=NewModelCraftParameter()
# c.setParameter()
c=CraftParameterAdapter(ModelCCraftParameter)
c.setParameter()

 桥模式

角色:

  抽象

  细化抽象

  实现者

  具体实现者

场景:当事务有两个以上维度,两个维度都可以拓展

优点:

  抽象和实现分离

  具有优秀的拓展能力

from abc import ABCMeta, abstractmethod
#抽象
class Shape(metaclass=ABCMeta):
    def __init__(self,color):
        self.color = color
    @abstractmethod
    def draw(self):
        pass
#实现者
class Color(metaclass=ABCMeta):
    @abstractmethod
    def paint(self,shape):
        pass
#细化抽象
class Triangle(Shape):
    name = "三角形"
    def draw(self):
        self.color.paint(self)

class Circle(Shape):
    name = "三角形"
    def draw(self):
        self.color.paint(self)
#具体实现者
class Red(Color):
    def paint(self,shape):
        print(f"红色的{shape.name}")

shape = Triangle(Red())
shape.draw()

 组合模式

适用于:部分–整体结构

优点:

  包含了基本对象和组合对象的类层次结构

  简化客户端代码,可以一致的使用组合对象和单个对象

  更容易增加新类型组件

from abc import ABCMeta, abstractmethod

#抽象组件
class ModelType(metaclass=ABCMeta):
    @abstractmethod
    def printModelType(self):
        pass

#叶子组件最小的节点
class SonModel(ModelType):
    def __init__(self, modelName):
        self.modelName = modelName

    def __str__(self):
        return f"机型{self.modelName}"

    def printModelType(self):
        print(self)

class ParentModelType(ModelType):
    def __init__(self,parentModelType,model):
        self.parentModelType = parentModelType
        self.model = model

    def __str__(self):
        return f"{self.parentModelType}旗下的[{self.model}]"

    def printModelType(self):
        print(self)
#复合组件
class Brand(ModelType):
    def __init__(self, iterable):
        self.sonModel = [m for m in iterable]

    def printModelType(self):
        for i in self.sonModel:
            i.printModelType()

# p = ParentModelType("setex757",SonModel("水流-02"))
# p.printModelType()
s1 = SonModel("水流-02")
p1 =ParentModelType("setex757",s1)
b = Brand([s1,p1])
b.printModelType()

 外观模式

比较简单:高层代码不需要知道低层代码,只需要用封装好的就行

定义:为子系统的接口提空一个一致的界面,定义一个高层接口,这接口使得系统更容易使用

角色:

  外观

  子系统类

优点:

  减少系统依赖

  提高灵活性

  提高安全性

class LendingSinger:
    def start(self):
        print("主唱开始唱")

    def stop(self):
        print("主唱闭嘴")

class Bass:
    def start(self):
        print("贝斯开始演奏")

    def stop(self):
        print("贝斯停止演奏")

class Keyboard:
    def start(self):
        print("键盘手开始演奏")

    def stop(self):
        print("键盘手停止演奏")

#更高级级别的类:乐队
#通过高系统调用来封装子系统
class Band:
    def __init__(self):
        self.lengdingSinger = LendingSinger()
        self.bass = Bass()
        self.keyboard = Keyboard()

    def start(self):
        self.bass.start()
        self.lengdingSinger.start()
        self.keyboard.start()

    def stop(self):
        self.keyboard.stop()
        self.bass.stop()
        self.lengdingSinger.stop()

b=Band()
b.start()
b.stop()

 模板方法模式

定义:先写一个骨架,其中的一些细节可以延迟实现,模板方法可以使得子类不改变骨架就可以重新定义某些改变

角色:

  抽象类:定义原子操作(或者叫钩子操作),实现一个模板方法骨架

  具体类:实现原子操作

依旧拿上面的乐队作为例子

from abc import ABCMeta , abstractmethod
from time import sleep


class Band:
    @abstractmethod
    def lengdingSinger(self):
        pass

    @abstractmethod
    def bass(self):
        pass

    @abstractmethod
    def keyboard(self):#原子操作
        pass

    def run(self): #模板方法
        self.bass()
        while True:
            try:
                self.lengdingSinger()
                sleep(1)
            except KeyboardInterrupt:
                break
        self.keyboard()
#原子操作定义好,等后面在子类里面实现
class NewBand(Band):
    def lengdingSinger(self):
        print("主唱无伴奏solo")

    def bass(self):
        print("贝斯进")

    def keyboard(self):
        print("键盘手进")

b = NewBand().run()

 

张贴在2