经典设计模式实战演练
课程简介
⾯向对象的程序应该具有可维护性,代码可复⽤性,扩展性以及灵活性。为了实现以上⽬的,前辈们从实践中总结出了⼀套可套⽤的武功招式,这就是设计模式。使⽤设计模式可以让你写出⼀⼿令⼈赏⼼悦⽬的代码。
我认为每⼀个后端开发者都应该学习设计模式,它是代码的精华,是程序发展的强⼒⽀撑,是能够让你发出惊叹的神来之笔。
本课程共有 10 篇,结合作者的开发经验,从理论到实战,剖析设计模式经典案例,帮助读者掌握将设计模式应⽤于实际项⽬开发的能⼒。
课程主要分为两⼤部分:
第⼀部分(第01-09课),介绍常⽤的⼏种设计模式,通过具体案例的分析与代码实现带领⼤家深⼊学习与理解设计模式;
第⼆部分(第10课),将结合多种设计模式⼿把⼿带领⼤家开发⼀个综合案例,提升设计模式实战的能⼒。
作者介绍
周君,资深后端⼯程师,CSDN 博客专家,精通 PHP、Java、Web 开发。多年实战经验,热衷分享。
课程内容
导读:如何学好设计模式
0.1 什么是设计模式
设计模式( Design Pattern )代表了最佳的实践,通常被有经验的⾯向对象的软件开发⼈员所采⽤。设计模式是软件开发⼈员在软件开发过程中⾯临的⼀般问题的解决⽅案。这些解决⽅案是众多软件开发⼈员经过相当长⼀段时间的试验和错误总结出来的。
上⾯的解释来⾃于⽹络,是⽐较标准的定义,可以从中筛选出⼏个关键字来帮助我们理解什么是设计模式:
最佳实践单例模式的几种实现方式
解决⽅案
试验和错误总结
从上⾯的三个关键词中可以总结出,设计模式就是在针对编码过程中遇到的问题总结出来的最佳解决⽅案。
那么这些问题指的是什么问题呢?⾯向对象的程序应该具有可维护性、代码可复⽤性、扩展性及灵活性,要解决的问题就是代码可维护性问题、复⽤性问题、扩展性问题及灵活性问题。
简单来说,设计模式就是指导你如何写出可维护、可复⽤、可扩展及灵活的代码。
0.2 设计模式分类
设计模式总共有 23 种,总体来说可以分为三⼤类:创建型模式( Creational Patterns )、结构型模式( Structural Patterns )和⾏为型模式( Behavioral Patterns )。
分类关注点包含
创建型模式关注于对象的创建,同时隐
藏创建逻辑
⼯⼚模式、抽象⼯⼚模式、单例模式、建造者模式、原型模式
结构型
模式
关注类和对象之间的组合适配器模式、过滤器模式、装饰模式、享元模式、代理模式、外观模式、组合模式、桥接模式
⾏为型模式关注对象之间的通信
责任链模式、命令模式、中介者模式、观察者模式、状态模式、策略模式、模板模式、空对象模式、备忘录模式、
迭代器模式、解释器模式、访问者模式
上⾯的三种分类说明,有助于在开发时思考当前场景应该使⽤哪种分类。⼤家不⼀定要全部记住,有个⼤概的了解即可。
0.3 学习设计模式
1. 为什么要学设计模式
写出可维护、可复⽤、可扩展及灵活的代码是我们的⽬的,也是学习设计模式的理由,但是这个理由对我们来说太抽象,下⾯从 “ 读 ” 和“ 写 ” 两⽅⾯来说明到底为什么要学习设计模式。
读
作为开发⼈员,不可避免地要接触其他⼈写的代码,有的是⼀些知名的库或框架,例如 Spring 、Shiro 等。但是当我们去阅读这些框架源码的时候会发现⽆从下⼿,因为类太多了,关系太复杂,⽽且很多类的命名看不懂,⽐如 xxxBuilder 、xxxStrategy 、xxxFilter 等,⼀个词看不懂就可能导致你直接放弃继续阅读。
如果没有学过设计模式,⾃然看不懂,学习设计模式可以有效地帮助你阅读代码,即便不能百分百帮到你,⾄少也能帮到百分之三四⼗。
写
每⼀个开发⼈员必然喷过其他⼈写的代码,觉得其他⼈的代码有的写得很垃圾,尤其是要扩展功能或者修改功能的时候,恨不得全部删掉重新写,其实在其他⼈看来你的代码也是如此。所以写出⼀⼿让⼈⽆话可说的代码是很有必要的,不仅可以满⾜你的⼩⼩成就感,也可以让你的程序更快速稳定地发
展。
在⼀个项⽬组中,如果⼤家都学习过设计模式,那么当你阅读或修改同事写的代码时也将得⼼应⼿,少了很多⿇烦。
2. 如何学好设计模式
如今⽹上和书上都有⼤量的设计模式教程,但是他们⼤部分都有⼀个共同点:仅仅使⽤⽣活中的例⼦。
⽐如前⼏年我第⼀次学习设计模式,在学到适配器模式时,教程中抛出了⼀个电器的插头问题:
你家插座只有三头的,但电器插头是两头的,怎么办?弄个插头适配器将两头转换成三头。
Nice,这个例⼦简单明了,作为新⼿的我瞬间明⽩了适配器的含义,就是在不兼容的双⽅中间做⼀层转化。但是后来发现在实际编码中根本⽤不上这个设计模式,因为我不会⽤。
⽣活中的例⼦的确可以帮助我们理解设计模式,这是⽏庸置疑的,但是想要真正⽤好设计模式,实际项⽬中的案例是必不可少的,这也是我写这门课的原因,希望通过分析实际案例,能够帮到更多想要学习设计模式的同⾏。
下⾯给出⼏点更加具体的建议:
从⽣活例⼦中去理解设计模式;
从实际案例去了解设计模式的使⽤场景;
动⼿实践,在学完实际案例之后,不妨动⼿写⼀写,不要写⽣活中的例⼦,⾃⼰构造⼀个⼩功能,⽤上你的设计模式;
改变⾃⼰的意识,在开发或修改⼀个功能时,⾸先要下意识地去思考这个功能将来在修改和扩展上会遇到什么问题,能否⽤上设计模式。记住⼀定要思考、⼀定要思考、⼀定要思考,即便最终⽤不上,也能让你回顾⼀遍设计模式的内容,使其知识更牢固。很多开发者不是不会⽤,⽽是根本没有想过要⽤设计模式,久⽽久之这⽅⾯的能⼒⾃然就弱化了。
0.4 课程说明
1. 课程内容
本课程每⼀篇⽂章都包含三⼤部分:
解释和理解设计模式;
⾄少介绍⼀个实际案例( 实际案例有些是我⾃⼰写的,有些来⾃于已有的框架或库 );
设计模式优缺点。
2. 必要准备
本课程将使⽤ Java 语⾔讲解设计模式,虽然设计模式与语⾔本⾝⽆关,但是本课程中有许多实际案例都是来⾃于知名的 Java 框架源码,如果没有 Java 基础,学习效果可能不佳。
除了要求 Java 基础之外,还需要了解 UML 图,如果不了解 UML,只需要知道以下⼏种 UML 关系即可:
泛化,可以简单地理解为继承关系;
实现,⼀般是接⼝和实现类之间的关系;
关联,⼀种拥有关系,⽐如⽼师类中有学⽣列表,那么⽼师类和学⽣类就是拥有关系;
聚合,整体与部分的关系,但是整体和部分是可以分离⽽独⽴存在的,如汽车类和轮胎类;
组合,整体与部分的关系,但是⼆者不可分离,分离了就没有意义了,例如,公司类和部门类,没有
公司就没有部门;
依赖,⼀种使⽤关系,例如创建 A 类必须要有 B 类。
参考下图:
记不住也没关系,后续课程主要使⽤泛化和实现这两种,先记住这两种即可,如果有遇到看不懂的再回头来看⼀眼。
第01课:策略模式
1.1 课程概述
策略模式定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独⽴于使⽤算法的客户。
⼀般情况下我们是将⼀种⾏为写成⼀个类⽅法,⽐如计算器类中有加、减、乘、除四种⽅法,⽽策略模式则是将每⼀种算法都写成⼀个类,然后动态地选择使⽤哪⼀个算法。
这⾥所说的算法并不是指 “ 冒泡排序算法 ” 、“ 搜索算法 ” 之类的算法,它可以是⼀段代码、⼀个请求、⼀个业务操作。
策略模式如图:
从上图可以看到,我们将操作封装到类中,他们实现了同⼀个接⼝,然后在 Context 中调⽤。
这⾥我们举⼀个计算器的例⼦:
此例中,为加法和减法分别创建了⼀个类。
其实策略不⼀定要命名为 Strategy ,Context 不⼀定要叫 Context ,可以根据实际情况⾃⼰命名,在计算器的例⼦中,你如果⾮要命名
为 Strategy 和 Context ,反⽽让⼈产⽣疑惑。
实际代码也很简单,具体如下。
Operation 接⼝:
public interface Operation { public int doOperation(int num1, int num2);}
两个实现类 —— 加法和减法:
public class OperationAdd implements Operation{ @Override public int doOperation(int num1, int num2) { return num1 + num2; }}public class O 计算器类:
public class Calculator { private Operation operation; public void setOperation(Operation operation){ this.operation = operation; } public int doO 使⽤:
Calculator calculator = new Calculator();calculator.setOperation(new OperationAdd());int result = calculator.doOperation(1,2);System.out.println(result);
使⽤计算器类时,如果要进⾏加法运算,就 New ⼀个加法类传⼊,减法也是同理。
看到这⾥,相信⼤家⼀定会有疑惑,为什么要把加、减、乘、除四则运算分别封装到类中?直接在 Calculator 中写 add() 、sub() 等⽅法
不是更⽅便吗?甚⾄如果要添加其他的运算⽅法,每次都要创建⼀个类,反⽽更⿇烦。
的确,⽤了策略模式之后代码⽐普通写法多了⼀些,但是这⾥假设⼀种场景:把写好的计算器代码打包好作为⼀个库发布出去给其他⼈⽤,
其他⼈发现你的计算器中只有加、减、乘、除四个⽅法,⽽他想增加平⽅、开⽅等功能,怎么办?
如果是⽤普通写法写的计算器,想要增加功能唯⼀的办法就是修改你写好的 Calculator ,增加平⽅和开⽅两个 method 。
可是你提供的是⼀个 jar 包啊,jar 包,jar…jar…jar…jar…包……
就算你提供的是源码,你希望其他⼈可以随意修改你写好的代码吗?⼀般我们发布出去的开源框架或库都是经过千锤百炼、经过测试的代
码,其他⼈随意修改我们的源码很容易产⽣不可预知的错误。
如果你⽤的是策略模式,那么其他⼈想要增加平⽅或开平⽅功能,只需要⾃⼰定义⼀个类实现你的 Operation 接⼝,然后调⽤
calculator.setOperation(new 平⽅类()); 即可。
看到这⾥相信你已经对策略模式有了⼀定的好感,甚⾄惊叹⼀声:哇,还有这种操作?
顺便提⼀嘴,这⾥很好的体现了⼀个设计模式的基本原则:开闭原则。开闭原则说的是 ” 对修改关闭、对扩展开放 “ 。对修改关闭就是不
希望别⼈修改我们的代码,此路不通,对扩展开放就是希望别⼈以扩展的⽅式增加功能,策略模式把开闭原则体现得淋漓尽致。
1.2 实际案例
1. 主题
隔壁⽼王准备开发⼀个客户端框架,允许其他的开发者进⾏⼆次开发,其中有⼀个更换主题的功能,开发者们可以⾃⼰定义主题。⽼王很快
就想到了策略模式,并且提供了⼀个默认主题 DefaultTheme :
代码:
public interface Theme { public void showTheme();}public class DefaultTheme implements Theme { @Override public void showTheme() { //此处设置主使⽤:
ThemeManager themeManager = new ThemeManager();themeManager.setTheme(new DefaultTheme());themeManager.showTheme();
看完更换主题的案例代码,你会发现跟计算器惊⼈地相似,没错,所谓设计模式就是前⼈总结出来的武功套路,经常可以直接套⽤。当然也
要灵活地根据实际情况进⾏修改,设计模式想要传达给我们的更多的是⼀种编程思想。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论