第二十一天
面向对象编程
# 面向过程:重点在于 “做什么”,使用大量的函数解决
# 优点:思维简单,容易实现
# 缺点:当需求发生改变的时候,不容易维护,不容易扩展
# 适合场景:底层的操作系统,服务器,中间件。。。。
# 面向对象:重点在于“谁” ,谁有什么,有什么行为
# 优点:当需求发生改变时,系统容易扩展
# 缺点:跟面向过程相比,复杂。跟面向切面相比,容易产生代码的冗余。
# 适合的场景:应用系统的开发。
# 人,起床,穿衣服,开门(开自己家楼门),锁门(门),开车(车)
# Person Door Car
# 人和车之间,人和门之间都是弱依赖。
# 人的名字
class Person: def __init__(self, name): self.name = name def getup(self): print("起床") def getdress(self): print("穿衣服") def openDoor(self, door): door.opendoor() def lockDoor(self, door): door.lockdoor() def drive(self, car): car.driver() def working(self): pass class Door: def __init__(self, name): self.name = name def opendoor(self): print("打开{}".format(self.name)) def lockdoor(self): print("锁门{}".format(self.name)) def modify(self): print("修理门") class Car: def __init__(self): self.name = None def driver(self): print("开{}车".format(self.name)) class AUDICar(Car): def __init__(self): super().__init__() self.name = "奥迪A6" p = Person("张三") p.getup() p.getdress() housedoor = Door("自己家门") p.openDoor(housedoor) p.lockDoor(housedoor) audiCar = AUDICar() p.drive(audiCar) p.working()
# 面向对象的相关概念
1. OO 面向对象 object-oriented
# 以对象为中心,以类和继承为构造机制,来认识或者理解客观世界的设计。
2.OOA 面向对象分析法
# 开发之前面向对象的分析。针对OO方法所需要的 素材记性归类分析和整理。
# 对于OO的细化工作,得到OO的属性和方法。
# OOA的主要原则
(1)抽象
# 编程:算法和数据结构 抽象把业务整理成合理的算法和数据结构。
# 抽象定义:从许多事务中舍弃个别的,非本质的特征,抽取共同,本质的特征,这就是抽象
# 设计class,把所有的对象分析成Class
# 抽象的原则:
# 过程抽象:在类中创建什么样的方法。类中方法
# 数据抽象:在类中应该有什么样的数据类型。类中属性
(2) 封装:就是把对象的属性和方法结合为一个不可分割系统单位,尽量对外隐藏内部的设计细节。
# python通过定义私有属性和私有方法 __name
# 为了能够让用户便捷的访问,需要使用property函数或者property装饰器。
class Tea:
def __init__(self, name, price):
self.__name = name
self.__price = price
def get_name(self):
return self.__name
name = property(get_name)
# def __del__(self):
# print("tea被删除")
(3)继承:特殊类的对象拥有一般类的全部属性和方法。把具有一般和特殊关系的类设计成继承。
# 一般:父类
# 特殊:子类
# 设计原则:父类 < 子类
class RedTea(Tea):
def __init__(self, name, price, level):
self.level = level
super().__init__(name, price)
(4)分类:是抽象原则应用对象描述的一种表现形式。把具有相同属性或者相同方法对象先划分成一类,
# 其他的类在这个类基础上扩展。
class BaseCold: def store(self): print("冷饮储藏") class BaseHot: def store(self): print("热饮储藏") class iceCream(BaseCold): pass
(5)聚合:组装,可以看成是把一个复杂的事务看成由若干事务组装起来。若干事务和复杂的事务之间强依赖。整体和部分之间的关系。
# A必须有B class Milk: pass # def __del__(self): # print("milk被删除") class MilkTea: def __init__(self, milk, tea, name, price): self.milk = milk self.tea = tea self.name = name self.price = price # def __del__(self): # print("奶茶被删除") milk = Milk() tea = Tea("红茶", 2) mt = MilkTea(milk, tea, "牛奶红茶", 20) # milk和milktea之间就是聚合关系 del mt
创建整体时,必须先有部分,才能创建整体
删除整体的时候,部分也会被跟着删除。
(6)关联:比较弱的类和类之间的关系,强调的是A可以有B
class MilkTea: def __init__(self, milk, tea, name, price): self.milk = milk self.tea = tea self.name = name self.price = price def addSuger(self, suger): suger.addSuguer(2) # def __del__(self): # print("奶茶被删除") class Suger: def addSuguer(self, n): print("加入{}糖".format(n)) milk = Milk() tea = Tea("红茶", 2) mt = MilkTea(milk, tea, "牛奶红茶", 20)
(7)消息通信:要求对象和对象之间只能通过消息进行通信(需要调用对应方法来访问属性)
# 而不是直接访问属性。封装
3. OOD面向对象的设计
# 是面向对象分析之后,在做编码之前的一个设计工作。
# 系统设计目标:
"""
(1)可扩展:保证新性能可以很容易的加入到先有的系统。不影响已有的内容
(2)可修改:当修改一部分代码的时候,尽量不影响其他相关的部分。
(3)可替代:调用父类的地方 可以用子类代替,说明父子关系实现的是对的。
"""
# 为了达到目标,希望遵守的原则SOLID原则
"""
1. 单一职责原则
2. 开放关闭原则
3. 里氏转换原则
4. 接口隔离原则
5. 依赖倒置原则
"""
1. 单一职责原则:一个类只做好一件事情。核心解耦。尽量将其他功能放入其他的类中。
2. 开放关闭原则:
# 对于模块和函数来说,应该扩展开放,对于修改关闭
# 类---扩展---继承
# 函数--扩展--装饰器
# 抽象出相对稳定的接口,这一部分一般不做修改。
# 扩展新功能,尽量通过其他新建的方式。
3.里氏替换原则:所有引用的基(父)类的地方必须能够透明使用其子类对象。判断对象之间的继承
# 关系是否合理。
# 在真正设计的时候,尽量采用的组合,而不是继承。
# 按照原则来说,子类对于父类的方法尽量不去重载
4. 接口隔离原则:多继承时,当创建一个接口(父类)尽量不强迫用户去实现不需要实现的内容。
# 茶: 加糖,加盐,做茶汤。
# 红茶(茶):如果不适合做茶汤,所以受限制。
# 最小继承。(父类中尽量保留最少的属性和方法,通用的)
# bike ride gps不应该出现在父类接口中。
5. 依赖倒置原则
# class Book(): # def getContent(self): # print("很久很久以前。。。。") # class Mother(): # def tellStory(self, book): # print("妈妈开始讲故事") # book.getContent() # b=Book() # m=Mother() # m.tellStory(b) class IReader(): def getContent(self): pass class Book(IReader): def getContent(self): print("很久很久以前。。。。") class News(IReader): def getContent(self): print("中国足球队。。。。") class Mother(): def tellStory(self, ireader): print("妈妈开始讲故事") ireader.getContent() b = Book() news = News() m = Mother() m.tellStory(b) m.tellStory(news)
# 解耦的目的
设计模式之工厂模式
"""
设计模式
GOP四个博士运用了5种原则,形成了一套经典设计模式
什么样的代码要抽取 ,什么样的代码不抽取,抽取的时候按什么规则抽取
"""
# 工厂模式:
class Shoe:
def __init__(self):
self.address="北京制造"
s=Shoe()
s.address="北京制造"
# 设计模式分为三种类型:
# 创建型模式
# 结构型模式
# 行为型模式
一、 创建型的模式
1. 工厂模式
"""
为了解决一个类不知道它所必须创建的对象是什么的时候。
解决的方式:
创建一个对象的接口,让子类决定实例化哪一个一个类,
创建Factory接口方法,按照客户的需求指定创建哪个类的对象
"""
# 创建圆形,画圆形
# class cirle:
# def __init__(self):
# self.name="circle"
# def draw(self):
# print("画一个圆形")
# class Rectangle:
# def __init__(self):
# self.name="rectangle"
# def draw(self):
# print("画一个矩形")
(1)简单工厂
class Shape: def __init__(self): self.shape_name=None # def getShape(self): # return self.shape_name class cirle(Shape): def __init__(self): super().__init__() self.name="circle" def draw(self): print("画一个圆形") class Rectangle(Shape): def __init__(self): super().__init__() self.name="rectangle" def draw(self): print("画一个矩形") class ShapeFactory: def create(self,shape_name): if shape_name=="circle": return cirle() if shape_name=="rectangle": return Rectangle() else: return None fac=ShapeFactory() obj=fac.create("circle") obj.draw() obj1=fac.create("rectangle") obj1.draw()
"""
优点:当指定创建某一个形状的时候,不需要调用不同的类创建对象
缺点:当新增加一个形状时,需要修改客户端的传入,还需要添加形状类,还需要修改工厂类。
"""
(2) 工厂方法模式
# 对于各个类有自己的工厂,对于原来简单工厂的扩展,
# 这个类不在负责具体产品的生产,只是指定规范,由其他扩展的工厂子类去完成对象的加工
class Shape: def __init__(self): self.shape_name=None # def getShape(self): # return self.shape_name class cirle(Shape): def __init__(self): super().__init__() self.name="circle" def draw(self): print("画一个圆形") class Rectangle(Shape): def __init__(self): super().__init__() self.name="rectangle" def draw(self ): print("画一个矩形") class Square(Shape): def __init__(self): super().__init__() self.name = "square" def draw(self): print("画一个正方形") class ShapeFactory: def create(self): pass class cirleFacotry(ShapeFactory): brand="圆形工厂" def create(self): return cirle() class rectangeFacotry(ShapeFactory): brand="长方工厂" def create(self): return Rectangle() class squareFacotry(ShapeFactory): brand="正方形工厂" def create(self): return Square() circleF=cirleFacotry() obj=circleF.create() print(circleF.brand) obj.draw() rectangeF=rectangeFacotry() obj1=rectangeF.create() print(rectangeF.brand) obj1.draw()
"""
优点:扩展性比较好,如果希望增加一个产品,增加一个产品类,增加一个工厂类
缺点:当每次加工产品,一定程度上,如果不需要批量从工厂中加工出特殊的对象,可能还不如普通的new
"""
(3) 抽象工厂模式
"""
抽象工厂:围绕着一个超级工厂去创建其他工厂,超级工厂又称为其他工厂的工厂。
对产品族中一套产品生成多个对象
"""
"""
实现思路:
产品族的工厂:包含了生产不同等级产品的方法
"""
# cpu class CPU: pass class IntelCpu(CPU): def __init__(self, name): self.name = name class AmdCpu(CPU): def __init__(self, name): self.name = name class Memory: pass class IntelMemory(Memory): def __init__(self, name): self.name = name class AmdMemory(Memory): def __init__(self, name): self.name = name class ComputerFacotry: def createCpu(self): pass def createMemory(self): pass class IntelFacotry(ComputerFacotry): computer_name = "Inter-7 computer" def createCpu(self): return IntelCpu("IntelCPU-2000") def createMemory(self): return IntelMemory("IntelMemory") class AmdFacotry(ComputerFacotry): computer_name = "AMD -n computer" def createCpu(self): return AmdCpu("AMDCPU-4000") def createMemory(self): return AmdMemory("AMDMemory")
# 希望要什么电脑,直接指定对应的工厂即可
# 电脑中已经对产品族中每一个产品进行了创建。
# ifa=IntelFacotry()
ifa = AmdFacotry()
cpu = ifa.createCpu()
memory = ifa.createMemory()
info = """
computer名字{}: cpu:{}
memory:{}
""".format(ifa.computer_name, cpu.name, memory.name)
print(info)
# 抽象工厂模式的优缺点:
"""
1. 客户端使用抽象工厂创建对象,客户端不需要知道具体的实现
2. 切换产品族非常容易,通过修改工厂即可
3. 增加新的具体工厂和产品族,对修改关闭,完全新建
缺点:
不容易扩展新的产品,需要向所有的工厂中添加新的产品。
应用场景:
1. 产品族不是经常修改。要修改就改一套产品族。
所以规定在产品族中的产品,一定是规定好的产品。
2. 一个系统不应当依赖于产品类实例如何被创建,也就是,当不关心创建本身的细节
只关心如何创建即可。
"""
"""
创建模式:new ,简单工厂、工厂方法、抽象工厂
"""
# 生产宝马车。
# 1. 没有工厂的时候,只能new,很可能需要创建好其他的对象,而且找好对象和对象之间的关系。
# 2. 简单工厂:相当于要宝马车的时候,向宝马车工厂要,不是自己去new
class BMWFacory:
def create(self):
pass
bf = BMWFacory()
b = bf.create()
# 3. 工厂方法:如果宝马车的系列原来的越多,一个工厂不够用,所以需要多个工厂进行加工。
# class BMWFacory:
# def create(self,type):
# # 判断具体要什么样宝马, 创建宝马对象,违反的关闭原则
# pass
class BMWFacory1:
def create(self):
pass
class BMWFacory2:
def create(self):
pass
class BMWFacory3:
def create(self):
pass
bf1 = BMWFacory1()
# 4. 抽象工厂:不同宝马车配不同的空调。宝马1系列配置A空调 ,宝马2系列配B空调。
class BMWFacory1A:
def create(self):
pass
class BMWFacory2B:
def create(self):
pass