设计模式
设计模式,即Design Patterns,是指在软件设计中,被反复使用的一种代码设计经验。 使用设计模式的目的是为了可重用代码,提高代码的可扩展性和可维护性
一:总纲
按照王老师的体系,23种设计模式,看上去很多,但万变不离其宗.一切设计模式,均是离不开这两张图.
具体来说,就如下两种:
1. 只有继承关系的:
DIP:依赖倒转原则,细节应当依赖于抽象,抽象不应当依赖于细节。
OCP:开闭原则,软件实体应当对扩展开放,对修改关闭.
特点:
只有一颗继承树
在设计模式里面的体现:
模板方法:比如,我写了一个白盒框架,现在要往里面加东西,我希望用户来进行手动添加,那么,我给用户一个接口,下面的子类型实现是可以进行任意安排的.
2. 继承+委托(delegation)
特点:两颗继承树
通过另一组继承树,对内在的实现进行了隐藏,具体的体现比如说:Factory方法,Adapter方法,装饰器模式,等等.
对于装饰器来说,可以认为这两颗树均是自己,通过自己对自己进行委托,进行功能的附加.
下面,我们来具体的对王老师上课所授的7种设计模式展开具体分析:
二:具体的7种设计模式
2.1 工厂方法:
用户是通过工厂类来得到新的对象,而不是通过new运算符来得到新的对象
常规情况
Product A=new ProductA();
工厂方法
Product B=ProductFactory.ProduceA();
正如船舶里面的水隔舱,工厂类对对象的创建与用户进行了隔离.对于用户而言,它是不知道它的要的产品具体叫什么,这个提供产品的事情,已经被工厂所取代.如果我们需要对功能进行修改的话,只需要动工厂的new的对象,客户端的程序实质上,是稳定的.
2.2 适配器模式
考虑下列情形:
假如我们在进行一个机器学习的项目,我们的核心算法,它需要提供一个numpy形式的矩阵,而我们的数据采集器,返回的矩阵,是一个excel文件.
这个时候,我们就需要一个适配器,帮我们干活了
它通过委托与接口,在二者之间建立了如下的桥梁;
2.3 装饰器模式
人靠衣装,在街上走,你会看到有穿T恤的,穿长袖夹克的,有穿背心的各种各样的人.
那么,如果要建立这样的关系的话,我们是可以通过继承来组合,也可以通过建立装饰器来进行委托.
如果是组合的话,问题会越来越麻烦.
设想,假如一开始所有人都穿T恤,那么到后来,秋天了,大家穿长袖的,有可能是里面套了一个背心,也有可能是里面传了一件毛衣,那么我们都用继承来进行处理的话,这个组合树,将会越来越大.问题很大!
这就是组合爆炸
所以,正确的做法是,让类学会穿衣服.不同的衣服,展现出不同的特性.有不同的功能
为每一个特性构造子类,并通过委派机制,添加到对象上.
基类实现最原始的功能,然后每一个装饰类实现一部分,逐层的去委派实现.
2.4策略模式
考虑如下的场景:
假如我们在写一个文本翻译的APP,用户输入文本,我们对其进行翻译.
我们一开始是采用SVD分解对文本进行词嵌入.后来,竞争对手纷纷采用了BERT来进行词嵌入,效果比我们好很多.那么,我们也想要用BERT来进行,不过由于考虑到以后的扩展,我们决定将词嵌入,放到一个方法类里面去进行.
即这里的策略类.
策略模式:
存在多种算法来处理同一个任务,但client需要根据需要动态切换算法.
我们可以为不同的实现算法构造抽象接口.利用委托,在运行时,动态传入Client倾向的算法类的实例.
其UML图如下;
2.5 模板模式
还是我们的文本翻译APP.
众所周知,NLP文本翻译任务,包含以下几个基本步骤:
文本预处理->文本词嵌入->Seq2Seq的生成
我们可以把这几个步骤抽出来作为模板,子类在继承时,进行实现.
让子类分别实现我们的模板里面的方法,预处理,词嵌入,文本生成.
他们,作事情的步骤时一样的,但具体的方法不同.让共性的步骤在公共实现.差异化的在子类实现.
2.6 迭代器模式
用途:我们给外界用户的往往是一个黑箱,如果用户有想要逛逛的需求的话,我们便要在既维护内在表示的基础上,又满足外界用户的需求.
在Java里面已经提供了下面的接口:
Iterable接口:实现这个的集合对象是可遍历的
Iterator接口:迭代器,实现这个的是可以进行显示/隐式的进行迭代的.
2.7 Visitor模式
简单点说:就是预留扩展点,以便日后的扩展
为我们的对象的特定Visit,运行时进行动态的绑定.操作可以灵活更改的.方便以后操作.
以上就是对于设计模式的一些总结与思考,谢谢.