设计模式
一、设计模式
1.1 如何理解设计模式
在IT行业中有很多前辈针对固定的一些问题设计出了固定的解决套路
1.2 设计模式总共有23种
设计模式目前为止总共有23种模式
1.3 设计模式的分类
如上图所示:
设计模式总共分为三类:
1.创建型模式
2.结构型模式
3.行为型模式
1.4 各分类的关键点
单例模式:某个类只能有一个实例,提供一个全局的访问点。
简单工厂:一个工厂类根据传入的参量决定创建出那一种产品类的实例。
工厂方法:定义一个创建对象的接口,让子类决定实例化那个类。
抽象工厂:创建相关或依赖对象的家族,而无需明确指定具体类。
建造者模式:封装一个复杂对象的构建过程,并可以按步骤构造。
原型模式:通过复制现有的实例来创建新的实例。
适配器模式:将一个类的方法接口转换成客户希望的另外一个接口。
组合模式:将对象组合成树形结构以表示“”部分-整体“”的层次结构。
装饰模式:动态的给对象添加新的功能。
代理模式:为其他对象提供一个代理以便控制这个对象的访问。
亨元(蝇量)模式:通过共享技术来有效的支持大量细粒度的对象。
外观模式:对外提供一个统一的方法,来访问子系统中的一群接口。
桥接模式:将抽象部分和它的实现部分分离,使它们都可以独立的变化。
模板模式:定义一个算法结构,而将一些步骤延迟到子类实现。
解释器模式:给定一个语言,定义它的文法的一种表示,并定义一个解释器。
策略模式:定义一系列算法,把他们封装起来,并且使它们可以相互替换。
状态模式:允许一个对象在其对象内部状态改变时改变它的行为。
观察者模式:对象间的一对多的依赖关系。
备忘录模式:在不破坏封装的前提下,保持对象的内部状态。
中介者模式:用一个中介对象来封装一系列的对象交互。
命令模式:将命令请求封装为一个对象,使得可以用不同的请求来进行参数化。
访问者模式:在不改变数据结构的前提下,增加作用于一组对象元素的新功能。
责任链模式:将请求的发送者和接收者解耦,使的多个对象都有处理这个请求的机会。
迭代器模式:一种遍历访问聚合对象中各个元素的方法,不暴露该对象的内部结构。
而我们现在只需要了解单例模式即可
1.5设计模式之单例模式
类加括号调用多次只能产生一个对象
1.6代码演示
class MyClass(object): pass obj1 = MyClass() obj2 = MyClass() obj3 = MyClass() # 一般情况下 类名加括号实例化对象 执行几次就会产生几个对象 print(id(obj1)) # 2241811157680 print(id(obj2)) # 2241811157792 print(id(obj3)) # 2241811158128 ''' 而我们有时候不需要类产生那么多不同的对象 类中有很多的很好用的方法 程序有很多地方都需要使用(通过对象调用) 如果产生的地方特别多 那么就会浪费一定的内存空间 所以需要单例 ''' # 单例可以有很多方法产生 # 第一种:使用元类 class MyMetaClass(type): # 继承元类 instance = None # 定义一个变量 def __call__(self, *args, **kwargs): if self.instance: # 如果存在返回之前赋值的 return self.instance obj = super().__call__(*args, **kwargs) # 产生一个空对象 self.instance = obj # 让对象赋值给 instance return obj # 返回空对象 class MyClass(metaclass=MyMetaClass): # 产生类的时候用MyMetaClass产生 def __init__(self, name): # 给空对象添加属性 self.name = name obj1 = MyClass('jason') obj2 = MyClass('kevin') obj3 = MyClass('tony') print(obj1.name) print(obj2.name) print(obj3.name) # 第二种: 使用装饰器 import settings # settings中的内容为: # HOST='1.1.1.1' # PORT=3306 def singleton(cls): # cls=Mysql _instance = cls(settings.HOST, settings.PORT) def wrapper(*args, **kwargs): if args or kwargs: obj = cls(*args, **kwargs) return obj return _instance return wrapper @singleton # Mysql=singleton(Mysql) class Mysql: def __init__(self, host, port): self.host = host self.port = port obj1 = Mysql() obj2 = Mysql() obj3 = Mysql() print(obj1.host) print(obj1.port) print(obj2.host) print(obj2.port) print(obj1 is obj2 is obj3) # True obj4 = Mysql('1.1.1.3', 3307) obj5 = Mysql('1.1.1.4', 3308) print(obj3 is obj4) # False # 第三种:定义一个类方法实现单例模式 import settings class Mysql: __instance = None def __init__(self, host, port): self.host = host self.port = port @classmethod def singleton(cls): if not cls.__instance: cls.__instance = cls(settings.HOST, settings.PORT) return cls.__instance obj1 = Mysql('1.1.1.2', 3306) obj2 = Mysql('1.1.1.3', 3307) print(obj1 is obj2) # False obj3 = Mysql.singleton() obj4 = Mysql.singleton() print(obj3 is obj4) # True
二、pickle模块
pickle模块与json模块一样都是对象数据序列化和反序列化的
而pickle模块支持python中所有的数据类型 而json模块有限制
但是pickle模块不能跨语言传输 兼容性差只能自己python玩
而json可以跨语言传输
为了我们接下来要编写的选课系统才学的 后续我们不会再用
因为有更高级的方法>>>:ORM(对象关系映射)
import json import pickle class MyClass(object): def __init__(self, name): self.name = name obj = MyClass('jason') # 我们现在需要把对象obj保存到文件中 # 1. 我们先使用文件操作看能不能写文件 with open(r'a.txt', 'w', encoding='utf8')as f: f.write(obj) # 会报错 因为使用write()只能写字符串不能是对象 # 2. 使用json格式 with open(r'a.txt', 'w', encoding='utf8')as f: json.dump(obj, f) # 也会报错 因为json格式不支持对象序列化 with open(r'a.txt', 'wb')as f: pickle.dump(obj, f) # 这样就能保存到文件中 但是使用pickle模块是二进制形式的
三、选课系统项目分析
选课系统 角色:学校、学员、课程、讲师 要求: 1. 创建北京、上海 2 所学校 2. 创建linux , python , go 3个课程 , linux\py 在北京开, go 在上海开 3. 课程包含,周期,价格,通过学校创建课程 4. 通过学校创建班级, 班级关联课程、讲师5. 创建学员时,选择学校,关联班级 5. 创建讲师角色时要关联学校, 6. 提供三个角色接口 6.1 学员视图, 可以注册, 交学费, 选择班级, 6.2 讲师视图, 讲师可管理自己的班级, 上课时选择班级, 查看班级学员列表 , 修改所管理的学员的成绩 6.3 管理视图,创建讲师, 创建班级,创建课程 7. 上面的操作产生的数据都通过pickle序列化保存到文件里 功能分析 管理员功能(最核心) 1.注册 2.登录 3.创建讲师 4.创建学校 5.创建课程 讲师功能 1.注册 2.登录 3.选择教授课程 4.查看教授课程 5.管理课程分数 学生功能 1.注册 2.登录 3.选择学校 4.选择课程 5.查看分数
三层架构
功能展示层
src.py
admin_view.py
teacher_view.py
student_view.py
核心逻辑层
admin_interface.py
teacher_interface.py
student_interface.py
数据处理层
db_hanlder.py
model.py
五、作业
5.1 描述出选课系统管理员注册功能完整逻辑
1.在admin.view中编写一个注册功能 2.在这个功能中获取姓名和密码 3.然后调用admin_interface中的注册函数 4.在这个函数调用model中的admin类做判断是否已注册 5.在model中创建两个方法一个是保存数据一个是获取数据 6.保存数据是在db文件夹中利用类名在创建一个文件夹 就是利用类名拼接一个路径创建 而类名的获取是 对象.__class__.__name__方法获得 7.然后在类名中创建管理员的文件文件名用获取到的名字 也是利用os拼接一个路径创建 而对象的名字获取的方法是 对象.name 就能够保存 8.然后就是获取这个路径就能够判断获取的名字是否存在 存在就不注册 不存在就注册 9.而想要获取的话我们传入的是对象而我们只能使用类的方式拼接 所以我们只能使用语法糖@classmethod让这个方法变成类的方法 这样我们就可以使用类名.name就可以获取类中的姓名