唐抉的个人博客

设计模式的学习(一)

字数统计: 1.8k阅读时长: 6 min
2022/07/27

设计模式

设计模式为软件开发人员在开发过程中面临一般问题时的解决方案,共有33种,可将其分为四大类:创建型模式、结构型模式、行为型模式和J2EE模式。

创建型模式

创建型模式致力于将对象的创建与使用分离,着重于如何创建对象。

该分类下的设计模式有5种:工厂模式、抽象工厂模式、单例模式、建造者模式和原型模式。

结构型模式

结构型模式关注于类的继承和组合,着重于简化结构并识别类与对象之间的关系。

该分类下的设计模式有8种:适配器模式、桥接模式、过滤器模式、组合模式、装饰器模式、外观模式、享元模式和代理模式。

行为型模式

行为型模式关注于对象之间的交互以及彼此之间的响应性,着重于算法与对象间的职责分配。

该分类下的设计模式有12种:责任链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、空对象模式、策略模式、模板模式和访问者模式。

J2EE模式

J2EE模式是为了开发基于Web的企业引用程序而构建的,特别关注表示层。

该分类下的设计模式有8种:MVC模式、业务代表模式、组合实体模式、数据访问对象模式、前端控制器模式、拦截过滤器模式、服务定位器模式和传输对象模式。

设计模式的六大原则(SOLID)

单一职责原则(Single Responsibility Principle)

不要存在多于一个导致类变更的原因。即每个类都应只实现单一的职责。

开放封闭原则(Open Closed Principle)

对扩展开放,对修改关闭。即在程序需要进行扩展时,不能去修改原有的代码,而是去扩展原有的代码。该原则的关键步骤是将代码抽象化。

里氏代换原则(Liskov Substitution Principle)

任何基类可以出现的地方,子类一定可以出现。该原则是继承复用的基石,只有当派生类可以替换掉基类,且软件单位的功能不受到影响时,基类才能真正被复用,而派生类也能够在基类的基础上增加新的行为。

该原则作为面向对象设计的基本原则之一,是对开闭原则的补充,是对实现抽象化的具体步骤的规范。

迪米特原则,又称最少知道原则(Law of Demeter)

一个类对自己依赖的类知道的越少越好。即无论被依赖的类复杂度有多高,都应将其逻辑封装在方法的内部后,在通过public方法提供给外部。使得当被依赖的类变化时,该类受到的影响最小。

接口隔离原则(Interface Segregation Principle)

每个接口不应存在子类用不到却必须实现的方法,若存在这种情况,应将接口拆分。为降低类之间的耦合度,使用多个隔离的接口比只使用单个接口要好。

依赖倒置原则(Dependence Inversion Principle)

针对接口编程,依赖于抽象而不依赖于具体。即用到具体类时,不与具体类交互,而与该具体类的上层接口交互。

该原则是开闭原则的基础。

本文中主要讲解最常用的设计模式之一:策略模式。

策略模式

策略模式定义了一系列的算法,并将每个算法都封装了起来,使得算法之间可以相互替换,且算法的改变不会影响使用算法的用户。策略模式属于对象行为型模式,其通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。

策略模式的优点

1、可避免使用多重条件语句,如多个if...else条件分支、switch...case语句。

2、提供了一系列可供重用的算法组,适当使用继承可以将算法族的公共代码转移到父类里,从而避免重复的代码。

3、可提供相同行为的不同实现,用户可根据不同时间或空间选择不同的实现方式。

4、可在不修改源代码的前提下,灵活增加新算法。

5、将算法的使用放到环境类中,算法的实现移到具体策略类中,实现了二者的分离。

策略模式的缺点

1、客户端必须理解所有策略算法的区别,以便于选择恰当的算法类。

2、策略类较多时,维护难度较大。

策略模式的使用举例

例如这是伪代码优化前的大致逻辑,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
class Person{
int worknum;//工号
int age;//年龄
int reqNum;//查询数量
}

//如果是学生类型
boolean isStudent(Person pto){
if(pto.type == 'student'){

//开关关闭不请求
if(isstudentSwitchClose){
return false;
}

//请求只有一条记录
if(pto.reqNum==1){
return singleRemoteEOIinvoke(pto);//调用学生数据的点查接口

//请求超过一条
}else if(pto.reqNum>1){
return batchRemoteEOIinvoke(pto);//调用学生数据的批量接口
}

//如果是教师类型
}else if(pto.type=='teacher'){

//开关关闭不请求
if(isteacherSwitchClose){
return false;
}
//请求只有一条记录
if(pto.reqNum==1){
return singleRemoteMarketinvoke(pto);//调用教师数据的点查接口

//请求超过一条
}else if(pto.reqNum>1){
return batchRemoteMarketinvoke(pto);//调用教师数据的批量接口
}
}
}

例子中的代码存在较多的if分支,若使用策略模式来优化,代码将变成下面这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
interface GroupLabel {
boolean processBiz(Person pto);//该方法对应策略实现类的具体实现
String getType();//该方法是策略类的类型,对应着```if...else```条件判断的类型
}

//学生类型的策略实现类
studentGroupLablel implements GroupLabel{

//对应学生类型的条件分支里的实现
boolean processBiz(Person pto){

//开关关闭不请求
if(isstudentSwitchClose){
return false;
}

//请求只有一条记录
if(pto.reqNum==1){
return singleRemoteEOIinvoke(pto);//调用学生数据点查接口

//请求超过一条
}else if(pto.reqNum>1){

return batchRemoteEOIinvoke(pto);//调用远程大数据批量接口
}

}

//对应学生类型
String getType(){
return "student";
}
}

//教师类型的策略实现类
teacherGroupLablel implements GroupLabel{

//对应教师类型的条件分支里的实现
boolean processBiz(Person pto){

//开关关闭不请求
if(isteacherSwitchClose){
return false;
}

//请求只有一条记录
if(pto.reqNum==1){
return singleRemoteMarketinvoke(pto);//调用教师数据的点查接口

//请求超过一条
}else if(pto.reqNum>1){
return batchRemoteMarketinvoke(pto);//调用教师数据的批量接口
}

}

//对应教师类型
String getType(){
return "teacher";
}
}
CATALOG
  1. 1. 设计模式
    1. 1.1. 创建型模式
    2. 1.2. 结构型模式
    3. 1.3. 行为型模式
    4. 1.4. J2EE模式
  2. 2. 设计模式的六大原则(SOLID)
    1. 2.1. 单一职责原则(Single Responsibility Principle)
    2. 2.2. 开放封闭原则(Open Closed Principle)
    3. 2.3. 里氏代换原则(Liskov Substitution Principle)
    4. 2.4. 迪米特原则,又称最少知道原则(Law of Demeter)
    5. 2.5. 接口隔离原则(Interface Segregation Principle)
    6. 2.6. 依赖倒置原则(Dependence Inversion Principle)
  3. 3. 策略模式
    1. 3.1. 策略模式的优点
    2. 3.2. 策略模式的缺点
    3. 3.3. 策略模式的使用举例