11

面向对象设计原则和模式 - yetangjian

 2 years ago
source link: https://www.cnblogs.com/yetangjian/p/16449139.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

面向对象设计原则

开放封闭原则:

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

里氏替换原则:

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

依赖倒置原则:

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

工厂方法模式

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

  抽象工厂角色(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()

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK