1、开放封闭原则:一个软件实体如类,模块和函数应该对扩展开放,对修改关闭。即软件实体应尽量在不修改原有代码的情况下进行扩展
2、里氏替换原则 :所有引用父类的地方必须透明的使用其子类对象,父类和子类参数和返回值都应该是一致的
3、依赖倒转原则:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。即针对接口编程,不要针对实现编程。
4、接口隔离原则:建立单一接口,不要建立庞大臃肿的接口,尽量细化接口,接口中的方法尽量少。就像我们定义了一个动物类,会飞、会游泳、会跑,当我们实现实例的时候,我们实现老虎、但是老虎不会飞,这个飞就是臃肿的部分
5、迪米特法则:高内聚 低耦合
6、单一职责原则:不要存在多于一个导致类变更的原因,通常来讲:一个类只负责一项职责
设计模式(Design Pattern)是几十年的开发人员经过长时间的试验和摸索,总结出来的一套 程序设计标准。它使得设计方案更加通俗易懂
1.单例模式介绍
1.内容:保证一个类只有一个实例,并提供一个访问他的全局访问点 2.使用场景:当类只能有一个实例而且客户可以从一个总所周知的访问点访问他 3.例: 比如Test是一个类,你创建两个对象a=Test(), b=Test()在单例模式下a,b两个对象相同 4.优点:
- from abc import abstractmethod, ABCMeta
-
- class Singleton(object):
- def __new__(cls, *args, **kwargs): #new方法最后返回的是一个实例
- 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: #如果不传参数就不必赋值
- self.name = name
- a = MyClass("a") #第一次创建对象时传入的是"a",所以a.name=a
- print(a)
- print(a.name)
-
- b = MyClass('b') #第二次创建对象时传入的是"b",所以将name改成了b,所以b.name=b
- print(b)
- print(b.name)
-
- print(a) #在b创建实例化后name值已经改成了b所以 a.name=b
- print(a.name)
-
- # 注:可以看到实例a和b内存地址相同时一个实例
- # <__main__.MyClass object at 0x00FBACB0>
- # a
- # <__main__.MyClass object at 0x00FBACB0>
- # b
- # <__main__.MyClass object at 0x00FBACB0>
- # b
- 复制代码
通过对程序的调试可以知道,我们使用的__new__的方法要比__init__先执行,而且是静态方法,可以直接.调用,使用完成,才是真正的创建了一个实例
通过上面的代码我们可以知道实际上_instance是随便写的,就是在类创建成功的时候,增加了一个类属性(其实就是那个新生成的对象),用于后面在生成类的时候,走过__new__的时候,判断下类属性是否存在,存在就不进行创建过程了,把之前的类属性(也就是新对象)返回回去即可,要没有,证明第一次构建,调用父类的__new__Create and return a new object,保存并返回,实现了生成对象的唯一。
- @staticmethod # known case of __new__
- def __new__(cls, *more): # known special case of object.__new__
- """ Create and return a new object. See help(type) for accurate signature. """
- pass
- 复制代码
2.工厂模式
内容:不直接向客户端(创建的对象)暴露对象创建的细节,而是通过一个工厂类来负责创建各种类的实例
在简单工厂函数中,我们可以在不同的method中,实现不同类的实例化,同时可以将一些不必要暴露的参数隐藏起来,像时间戳、指定的字符串、指定enable_yuebao的参数不同。
- # 简单工厂模式
- from abc import abstractmethod, ABCMeta
-
- class Payment(metaclass=ABCMeta):
- @abstractmethod
- def pay(self, money):
- pass
-
- class Alipay(Payment):
- def __init__(self, enable_yuebao=False):
- self.enable_yuebao = enable_yuebao
-
- def pay(self, money):
- if self.enable_yuebao:
- 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 == "yuebao":
- return Alipay(True)
- elif method == "applepay":
- return ApplePay()
- else:
- raise NameError(method)
-
- f = PaymentFactory()
- p = f.create_payment("alipay") #创建一个Alipay对象,这里创建对象时不必关心需要传递那些参数
- p.pay(100)
- 复制代码
3.工厂方法模式
内容:定义一个用于创建对象的接口(工厂接口),让子类决定实例化那个参品类
- # 工厂方法模式
- from abc import abstractmethod, ABCMeta
- class Payment(metaclass=ABCMeta): #
- @abstractmethod
- def pay(self, money):
- pass
- class Alipay(Payment):
- def pay(self, money):
- 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 ApplePayFactory(PaymentFactory):
- def create_payment(self):
- return ApplePay()
-
- af = AlipayFactory()
- ali = af.create_payment()
- ali.pay(120)
- 复制代码
4.抽象工厂模式(解决多类产品)
内容: 定义一个工厂接口,让工厂子类来创建一系列相关或相互依赖的对象
例: 生产一部手机,需要手机壳,CPU,操作系统三类对象进行组装,其中每类对象都有不同的种类。 对每个具体工厂分别生产一部手机所需要的三个对象
特点:相比工厂方法模式,抽象工厂模式中的每个具体工厂都生产一套产品
适用场景: 强调一系类相关的产品对象得设计以便进行联合使用时
优点:
缺点: 难以支持新种类的(抽象)产品,产品类新增(扩展)即可,但是在工厂类中需要修改代码(违反了开闭原则)
- # 抽象工厂
- 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()
-
- # 手机信息:
- # 苹果CPU
- # iOS系统
- # 苹果手机壳
- 复制代码
5.建造者模式
是将一个复杂对象的构造与表现进行分离,利用多个步骤进行创建,同一个构建过程可用于创建多个不同的表现 简单来说,就是将一个复杂对象实例化的过程,按照自己的想法,一步步设置参数,定制一个我们需要的对象 构建者模式一般由产品(product)、 Director(指挥官)和 Builder(建设者)构成 Builder 用于定义目标对象部件的方法和参数 Director 用于构造一个 Builder 的接口,由 Director 去指导 Builder 生成一个复杂的对象产品(product)
以购买一辆车( 包含:准备钱、看车、试驾、购买 4 个步骤)为例
优点:隐藏了一个产品的内部结构和装配的过程、将构造代码和表示代码分开、可以对构造过程进行更精细的控制
理解:就是Car是一个产品,builder就是其中的每个部门,每个部门分别为车进行构建,director的部分就是将前面各个部门的工作进行按照一定的顺序组装,最终得到一个产品对象。
- from time import sleep
-
- #首先,定义一个车的实体,并定义属性变量
- class Car(object):
- def __init__(self):
- # 准备的钱
- self.money = None
-
- # 去哪里看车
- self.address = None
-
- # 试驾什么车
- self.car_name = None
-
- # 购买时间是
- self.buy_time = None
-
- def __str__(self):
- return "准备了:%s,去%s看车,试驾了%s,下单了,购买时间是:%s" % (self.money, self.address, self.car_name, self.buy_time)
-
- #创建一个 Builder,实例化一个 Car 对象
- class CarBuilder(object):
- def __init__(self):
- self.car = Car()
-
- def ready_money(self, money):
- """
- 准备的金额
- :param money:
- :return:
- """
- self.car.money = money
- sleep(0.5)
- return self
-
- def see_car(self, address):
- """
- 去哪里看车
- :param address:
- :return:
- """
- self.car.address = address
- sleep(0.5)
- return self
-
- def test_drive(self, car_name):
- """
- 试驾了什么车
- :param car_name:
- :return:
- """
- self.car.car_name = car_name
- sleep(0.5)
- return self
-
- def buy_car(self, buy_time):
- """
- 下单时间
- :param buy_time:
- :return:
- """
- self.car.buy_time = buy_time
- sleep(0.5)
- return self
-
- #创建 Director,创建 build 方法,使用 Builder 一步步构建一个车对象并返回
- class Director(object):
- def __init__(self):
- self.builder = None
-
- def build(self, builder): # 控制组装顺序
- self.builder = builder
- self.builder. ready_money("30万"). see_car("4S店"). test_drive("奥迪A4L"). buy_car("2022年8月1日")
-
- # 返回构建的对象
- return self.builder.car
-
- if __name__ == '__main__':
- # 实例化一个构建者对象
- car_builder = CarBuilder()
- # 实例化一个负责人
- director = Director()
-
- # 构建的对象
- car = director.build(car_builder)
-
- print(car)
- 复制代码
1.适配器模式
内容:将一个类的接口转换成客户希望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
1.适用场景:想使用一个已经存在的类,而他的接口不符合要求
2.两种实现方式:
- # 当我们需要改动部分的代码很少的时候,我们直接多继承+复写方法即可
- from abc import ABCMeta,abstractclassmethod
-
- class Payment(metaclass=ABCMeta):
- @abstractclassmethod
- def pay(self,money):
- pass
-
- class Alipay(Payment):
- def pay(self,money):
- print("阿里支付了{}元".format(money))
-
- class Weixinpay(Payment):
- def pay(self,money):
- print("微信支付了{}元".format(money))
-
- class Bankpay:
- def cost(self,money):
- print("银行卡支付{}元".format(money))
-
- class NewBankPay(Payment,Bankpay):
- def pay(self,money):
- self.cost(money)
-
- nb = NewBankPay()
- nb.pay(100)
- 复制代码
- from abc import ABCMeta,abstractclassmethod
-
- class Payment(metaclass=ABCMeta):
- @abstractclassmethod
- def pay(self,money):
- pass
-
- class Alipay(Payment):
- def pay(self,money):
- print("阿里支付了{}元".format(money))
-
- class Weixinpay(Payment):
- def pay(self,money):
- print("微信支付了{}元".format(money))
-
- # 当存在多个需要进行适配的代码的时候(对象适配器)
- class Bankpay:
- def cost(self,money):
- print("银行卡支付{}元".format(money))
-
- class Applepay:
- def cost(self,money):
- print("苹果支付{}元".format(money))
-
- class PaymentAdapter(Payment):
- def __init__(self,payment):
- self.payment = payment
-
- def pay(self,money):
- self.payment.cost(money)
-
- nb = PaymentAdapter(Bankpay())
- nb.pay(100)
- 复制代码
2.桥模式
内容:将一个事物的两个维度分离,使其都可以独立地变化。
- 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 Rectangle(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("红色的%s"%shape.name)
-
- class Green(Color):
- def paint(self,shape):
- print("绿色的%s"%shape.name)
-
- shape = Rectangle(Red())
- shape.draw()
- 复制代码
将shape和Color进行解除耦合之后,我们可以对任意一个维度进行扩展,比之前的GreenLine的这种更容易维护。
应用场景:当事物有两个维度的表现,两个维度都可能扩展
优点:抽象和实现分离,优秀的扩展能力
3.组合模式
- from abc import ABCMeta, abstractmethod
-
- # 抽象组件
- class Graphic(metaclass=ABCMeta):
- @abstractmethod
- def draw(self):
- pass
-
- # 叶子组件
- class Point(Graphic):
- def __init__(self,x,y):
- self.x = x
- self.y = y
-
- def __str__(self):
- return "点(%s, %s)"%(self.x, self.y)
-
- def draw(self):
- print(str(self))
-
- # 叶子组件
- class Line(Graphic):
- def __init__(self, p1, p2):
- self.p1 = p1
- self.p2 = p2
-
- def __str__(self):
- return "线段[%s, %s]" %(self.p1, self.p2)
-
- def draw(self):
- print(str(self))
-
- # 复合组件
- class Picture(Graphic):
- def __init__(self, iterable):
- self.children = []
- for g in iterable:
- self.add(g)
-
- def add(self,graphic):
- self.children.append(graphic)
-
- def draw(self):
- print("----复合图形----")
- for g in self.children:
- g.draw()
- print("----复合图形----")
-
-
- l = Line(Point(1,1),Point(2,2))
- print(l)
- l.draw()
-
- p1 = Point(2,3)
- l1 = Line(Point(3,4),Point(6,7))
- l2 = Line(Point(1,5),Point(2,8))
- pic1 = Picture([p1,l1,l2])
-
- pic1.draw()
- 复制代码
4. 外观模式
- class CPU:
- def run(self):
- print("CPU开始工作")
-
- def stop(self):
- print("CPU停止工作")
-
- class Disk:
- def run(self):
- print("硬盘开始工作")
-
- def stop(self):
- print("硬盘停止工作")
-
- class Memory:
- def run(self):
- print("内存开始工作")
-
- def stop(self):
- print("内存停止工作")
-
-
- class Computer:
- def __init__(self):
- self.CPU = CPU()
- self.Disk = Disk()
- self.Memory = Memory()
-
- def run(self):
- self.CPU.run()
- self.Disk.run()
- self.Memory.run()
-
- def stop(self):
- self.CPU.stop()
- self.Disk.stop()
- self.Memory.stop()
-
- computer = Computer()
- computer.run()
- computer.stop()
- 复制代码
5.代理模式
- from abc import ABCMeta,abstractclassmethod
- class Subject():
- @abstractclassmethod
- def get_content(self):
- pass
-
- @abstractclassmethod
- def set_content(self,content):
- pass
-
- class RealSubject(Subject):
- def __init__(self,filename):
- self.filename = filename
- f = open(self.filename,"r",encoding="utf-8")
- self.content = f.read()
- f.close()
-
- def get_content(self):
- return self.content
-
- def set_content(self,content):
- f = open(self.filename,"w",encoding="utf-8")
- f.write(content)
- f.close()
-
- """
- 这种方式的缺陷是,当我们实例化了对象之后,我们的self.content就会保存在内存中,文件过大,就会影响性能,使用虚代理解决
- subj = RealSubject("text.txt")
- subj.get_content()
- """
-
- class VirtualProxy(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()
-
- def set_content(self,content):
- if not self.subj:
- self.subj = RealSubject(self.filename)
- return self.subj.set_content(content)
-
- # 保护代理
- class ProtectedProxy(Subject):
- def __init__(self,filename):
- self.subj = RealSubject(filename)
-
- def get_content(self):
- return self.subj.get_content()
-
- def set_content(self,content):
- raise PermissionError("无权限处理此文件")
-
- # 并没有创建真正的RealSubject对象,不会占用太多内存
- subj = VirtualProxy("text.txt")
- print(subj.get_content())
- 复制代码
1.责任链模式
1.内容: 使多个对象都有机会处理请求, 从而避免请求的发送者和接受者之间的耦合关系. 将这些对象连城一条链, 并沿着这条链传递该请求, 直到有一个对象处理它为止.
2.角色:
3.适用场景
4.优点
- from abc import ABCMeta, abstractmethod
-
- class Handler(metaclass=ABCMeta):
- @abstractmethod
- def handle_level(self, day):
- pass
-
- class GeneralManager(Handler):
- def handle_level(self, day):
- if day < 10:
- print("总理经准假%d天"%day)
- else:
- print("请假超过10天,你还是辞职吧")
-
- class DepartmentManager(Handler):
- def __init__(self):
- self.next = GeneralManager()
- def handle_level(self, day):
- if day <=5:
- print("部门经理准假%d天"%day)
- else:
- print("部门经理职权不足")
- self.next.handle_level(day)
-
- class ProjectDirector(Handler):
- def __init__(self):
- self.next = DepartmentManager()
- def handle_level(self, day):
- if day<=3:
- print("项目主管准假%d天"%day)
- else:
- print("项目主管职权不足")
- self.next.handle_level(day)
-
- # 高层代码 client
- day = 8
- h = ProjectDirector()
- h.handle_level(day)
- 复制代码
2.观察者模式(发布-订阅模式)
1.内容: 定义对象间的一种一对多的依赖关系, 当一个对象的状态发生改变时, 所有依赖于它的对象都能得到通知并被自动更新. 观察者模式又称"发布-订阅"模式
2.角色:
3.适用场景:
当一个抽象模型有两方面, 其中一个方面依赖于另一个方面. 将这两者封装在独立对象中以使它们可以各自独立地改变和复用.
当对一个对象的改变需要同时改变其他对象, 而不知道具体有多少对象有待改变.
当一个对象必须通知其他对象, 而它又不能假定其他对象是谁. 换言之, 你不希望这些对象是紧密耦合的.
4.优点:
- from abc import ABCMeta, abstractmethod
-
- class Observer(metaclass=ABCMeta): # 抽象订阅者
- @abstractmethod
- def update(self, notice): # notice 是一个Notice类的对象
- pass
-
- class Notice: # 抽象发布者
- def __init__(self):
- self.observers = []
-
- def attach(self, obs):
- self.observers.append(obs)
-
- def detach(self, obs):
- self.observers.remove(obs)
-
- def notify(self): # 推送
- for obs in self.observers:
- obs.update(self)
-
- class StaffNotice(Notice):
- def __init__(self, company_info = None):
- super().__init__()
- self.__company_info = company_info # 处理成私有对象
-
- @property # 负责读
- def company_info(self):
- return self.__company_info
-
- @company_info.setter # 负责写
- def company_info(self, info):
- self.__company_info = info
- self.notify() # 关键代码, 推送给所有观察者
-
-
-
- class Staff(Observer):
- def __init__(self):
- self.company_info = None
-
- def update(self, notice):
- self.company_info = notice.company_info
-
- # Client
-
- notice = StaffNotice("初始公司信息")
- s1 = Staff()
- s2 = Staff()
- notice.attach(s1)
- notice.attach(s2)
- print(s1.company_info) # None
- notice.company_info = "公司今年业绩非常好,给大家发奖金"
- print(s1.company_info) # 被修改了
- print(s2.company_info) # 被修改了
- notice.detach(s2)
- notice.company_info = "公司明天放假"
- print(s1.company_info) # 被修改了
- print(s2.company_info) # 没有被修改
- 复制代码
3.策略模式
1.内容: 定义一系列的算法,把他们一个个封装起来,并且使他们可相互替换。本模式使得算法可独立于使用他们的客户而变化。
2.角色:
3.优点:
4.缺点:
- from abc import ABCMeta, abstractmethod
-
- class Strategy(metaclass=ABCMeta):
- @abstractmethod
- def execute(self, data):
- pass
-
- class FastStrategy(Strategy):
- def execute(self, data):
- print("用较快的策略处理%s"%data)
-
- class SlowStrategy(Strategy):
- def execute(self, data):
- print("用较慢的策略处理%s" % data)
-
- class Context:
- def __init__(self,data,strategy):
- self.data = data
- self.strategy = strategy
-
- def set_strategy(self, strategy):
- self.strategy = strategy
-
- def do_strategy(self):
- self.strategy.execute(self.data)
-
- # Client
- data = "[...]"
- s1 = FastStrategy()
- s2 = SlowStrategy()
- context = Context(data,s1)
- context.do_strategy()
- context.set_strategy(s2)
- context.do_strategy()
- 复制代码
4.模版方法模式
1.内容: 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义改算法的某些特定步骤。
2.角色:
3.适用场景:
- from abc import ABCMeta,abstractmethod
- from time import sleep
-
- class Window(metaclass=ABCMeta):
- @abstractmethod
- def star(self):
- pass
-
- @abstractmethod
- def repaint(self):
- pass
-
- @abstractmethod
- def stop(self):
- pass
-
- def run(self): # 模板方法
- self.star()
- while True:
- try:
- self.repaint()
- sleep(1)
- except KeyboardInterrupt:
- break
- self.stop()
-
- class MyWindow(Window):
- def __init__(self,msg):
- self.msg = msg
-
- def star(self):
- print("窗口开始运行")
-
- def stop(self):
- print("窗口结束运行")
-
- def repaint(self):
- print(self.msg)
-
- MyWindow("Hello World").run()
总结了很多有关于python面试的资料,希望能够帮助正在学习python的小伙伴。由于资料过多不便发表文章,创作不易,望小伙伴们能够给我一些动力继续创建更好的python类学习资料文章,
请多多支持和关注小作,别忘了点赞+评论+转发。右上角私信我回复【999】即可领取免费学习资料谢谢啦!