本章是关于设计模式的最后一讲,会讲到第三种设计模式——行为型模式,共11种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。这段时间一直在写关于设计模式的东西,终于写到一半了,写博文是个很费时间的东西,因为我得为读者负责,不论是图还是代码还是表述,都希望能尽量写清楚,以便读者理解,我想不论是我还是读者,都希望看到高质量的博文出来,从我本人出发,我会一直坚持下去,不断更新,源源动力来自于读者朋友们的不断支持,我会尽自己的努力,写好每一篇文章!希望大家能不断给出意见和建议,共同打造完美的博文!

学会技术,懂得分享!

有任何想法,请联系:egg

email:xtfggef@gmail.com   微博:http://weibo.com/xtfggef

如有转载,请说明出处:http://blog.csdn.net/zhangerqing


先来张图,看看这11中模式的关系:

第一类:通过父类与子类的关系进行实现。第二类:两个类之间。第三类:类的状态。第四类:通过中间类

13、策略模式(strategy)

策略模式定义了一系列算法,并将每个算法封装起来,使他们可以相互替换,且算法的变化不会影响到使用算法的客户。需要设计一个接口,为一系列实现类提供统一的方法,多个实现类实现该接口,设计一个抽象类(可有可无,属于辅助类),提供辅助函数,关系图如下:

图中ICalculator提供同意的方法,
AbstractCalculator是辅助类,提供辅助方法,接下来,依次实现下每个类:

首先统一接口:

[java] view plaincopy
  1. public interface ICalculator {
  2. public int calculate(String exp);
  3. }

辅助类:

[java] view plaincopy
  1. public abstract class AbstractCalculator {
  2. public int[] split(String exp,String opt){
  3. String array[] = exp.split(opt);
  4. int arrayInt[] = new int[2];
  5. arrayInt[0] = Integer.parseInt(array[0]);
  6. arrayInt[1] = Integer.parseInt(array[1]);
  7. return arrayInt;
  8. }
  9. }

三个实现类:

[java] view plaincopy
  1. public class Plus extends AbstractCalculator implements ICalculator {
  2. @Override
  3. public int calculate(String exp) {
  4. int arrayInt[] = split(exp,"\\+");
  5. return arrayInt[0]+arrayInt[1];
  6. }
  7. }
[java] view plaincopy
  1. public class Minus extends AbstractCalculator implements ICalculator {
  2. @Override
  3. public int calculate(String exp) {
  4. int arrayInt[] = split(exp,"-");
  5. return arrayInt[0]-arrayInt[1];
  6. }
  7. }
[java] view plaincopy
  1. public class Multiply extends AbstractCalculator implements ICalculator {
  2. @Override
  3. public int calculate(String exp) {
  4. int arrayInt[] = split(exp,"\\*");
  5. return arrayInt[0]*arrayInt[1];
  6. }
  7. }

简单的测试类:

[java] view plaincopy
  1. public class StrategyTest {
  2. public static void main(String[] args) {
  3. String exp = "2+8";
  4. ICalculator cal = new Plus();
  5. int result = cal.calculate(exp);
  6. System.out.println(result);
  7. }
  8. }

输出:10

策略模式的决定权在用户,系统本身提供不同算法的实现,新增或者删除算法,对各种算法做封装。因此,策略模式多用在算法决策系统中,外部用户只需要决定用哪个算法即可。

14、模板方法模式(Template Method)

解释一下模板方法模式,就是指:一个抽象类中,有一个主方法,再定义1...n个方法,可以是抽象的,也可以是实际的方法,定义一个类,继承该抽象类,重写抽象方法,通过调用抽象类,实现对子类的调用,先看个关系图:

就是在AbstractCalculator类中定义一个主方法calculate,calculate()调用spilt()等,Plus和Minus分别继承AbstractCalculator类,通过对AbstractCalculator的调用实现对子类的调用,看下面的例子:

[java] view plaincopy
  1. public abstract class AbstractCalculator {
  2. /*主方法,实现对本类其它方法的调用*/
  3. public final int calculate(String exp,String opt){
  4. int array[] = split(exp,opt);
  5. return calculate(array[0],array[1]);
  6. }
  7. /*被子类重写的方法*/
  8. abstract public int calculate(int num1,int num2);
  9. public int[] split(String exp,String opt){
  10. String array[] = exp.split(opt);
  11. int arrayInt[] = new int[2];
  12. arrayInt[0] = Integer.parseInt(array[0]);
  13. arrayInt[1] = Integer.parseInt(array[1]);
  14. return arrayInt;
  15. }
  16. }
[java] view plaincopy
  1. public class Plus extends AbstractCalculator {
  2. @Override
  3. public int calculate(int num1,int num2) {
  4. return num1 + num2;
  5. }
  6. }

测试类:

[java] view plaincopy
  1. public class StrategyTest {
  2. public static void main(String[] args) {
  3. String exp = "8+8";
  4. AbstractCalculator cal = new Plus();
  5. int result = cal.calculate(exp, "\\+");
  6. System.out.println(result);
  7. }
  8. }

我跟踪下这个小程序的执行过程:首先将exp和"\\+"做参数,调用AbstractCalculator类里的calculate(String,String)方法,在calculate(String,String)里调用同类的split(),之后再调用calculate(int ,int)方法,从这个方法进入到子类中,执行完return num1 + num2后,将值返回到AbstractCalculator类,赋给result,打印出来。正好验证了我们开头的思路。

15、观察者模式(Observer)

包括这个模式在内的接下来的四个模式,都是类和类之间的关系,不涉及到继承,学的时候应该 记得归纳,记得本文最开始的那个图。观察者模式很好理解,类似于邮件订阅和RSS订阅,当我们浏览一些博客或wiki时,经常会看到RSS图标,就这的意思是,当你订阅了该文章,如果后续有更新,会及时通知你。其实,简单来讲就一句话:当一个对象变化时,其它依赖该对象的对象都会收到通知,并且随着变化!对象之间是一种一对多的关系。先来看看关系图:

我解释下这些类的作用:MySubject类就是我们的主对象,Observer1和Observer2是依赖于MySubject的对象,当MySubject变化时,Observer1和Observer2必然变化。AbstractSubject类中定义着需要监控的对象列表,可以对其进行修改:增加或删除被监控对象,且当MySubject变化时,负责通知在列表内存在的对象。我们看实现代码:

一个Observer接口:

[java] view plaincopy
  1. public interface Observer {
  2. public void update();
  3. }

两个实现类:

[java] view plaincopy
  1. public class Observer1 implements Observer {
  2. @Override
  3. public void update() {
  4. System.out.println("observer1 has received!");
  5. }
  6. }
[java] view plaincopy
  1. public class Observer2 implements Observer {
  2. @Override
  3. public void update() {
  4. System.out.println("observer2 has received!");
  5. }
  6. }

Subject接口及实现类:

[java] view plaincopy
  1. public interface Subject {
  2. /*增加观察者*/
  3. public void add(Observer observer);
  4. /*删除观察者*/
  5. public void del(Observer observer);
  6. /*通知所有的观察者*/
  7. public void notifyObservers();
  8. /*自身的操作*/
  9. public void operation();
  10. }
[java] view plaincopy
  1. public abstract class AbstractSubject implements Subject {
  2. private Vector<Observer> vector = new Vector<Observer>();
  3. @Override
  4. public void add(Observer observer) {
  5. vector.add(observer);
  6. }
  7. @Override
  8. public void del(Observer observer) {
  9. vector.remove(observer);
  10. }
  11. @Override
  12. public void notifyObservers() {
  13. Enumeration<Observer> enumo = vector.elements();
  14. while(enumo.hasMoreElements()){
  15. enumo.nextElement().update();
  16. }
  17. }
  18. }
[java] view plaincopy
  1. public class MySubject extends AbstractSubject {
  2. @Override
  3. public void operation() {
  4. System.out.println("update self!");
  5. notifyObservers();
  6. }
  7. }

测试类:

[java] view plaincopy
  1. public class ObserverTest {
  2. public static void main(String[] args) {
  3. Subject sub = new MySubject();
  4. sub.add(new Observer1());
  5. sub.add(new Observer2());
  6. sub.operation();
  7. }
  8. }

输出:

update self!
observer1 has received!
observer2 has received!

这些东西,其实不难,只是有些抽象,不太容易整体理解,建议读者:根据关系图,新建项目,自己写代码(或者参考我的代码),按照总体思路走一遍,这样才能体会它的思想,理解起来容易!

欢迎广大读者随时指正,一起讨论,一起进步!

有问题,联系:egg

email:xtfggef@gmail.com      微博:http://weibo.com/xtfggef

16、迭代子模式(Iterator)

顾名思义,迭代器模式就是顺序访问聚集中的对象,一般来说,集合中非常常见,如果对集合类比较熟悉的话,理解本模式会十分轻松。这句话包含两层意思:一是需要遍历的对象,即聚集对象,二是迭代器对象,用于对聚集对象进行遍历访问。我们看下关系图:

这个思路和我们常用的一模一样,MyCollection中定义了集合的一些操作,MyIterator中定义了一系列迭代操作,且持有Collection实例,我们来看看实现代码:

两个接口:

[java] view plaincopy
  1. public interface Collection {
  2. public Iterator iterator();
  3. /*取得集合元素*/
  4. public Object get(int i);
  5. /*取得集合大小*/
  6. public int size();
  7. }
[java] view plaincopy
  1. public interface Iterator {
  2. //前移
  3. public Object previous();
  4. //后移
  5. public Object next();
  6. public boolean hasNext();
  7. //取得第一个元素
  8. public Object first();
  9. }

两个实现:

[java] view plaincopy
  1. public class MyCollection implements Collection {
  2. public String string[] = {"A","B","C","D","E"};
  3. @Override
  4. public Iterator iterator() {
  5. return new MyIterator(this);
  6. }
  7. @Override
  8. public Object get(int i) {
  9. return string[i];
  10. }
  11. @Override
  12. public int size() {
  13. return string.length;
  14. }
  15. }
[java] view plaincopy
  1. public class MyIterator implements Iterator {
  2. private Collection collection;
  3. private int pos = -1;
  4. public MyIterator(Collection collection){
  5. this.collection = collection;
  6. }
  7. @Override
  8. public Object previous() {
  9. if(pos > 0){
  10. pos--;
  11. }
  12. return collection.get(pos);
  13. }
  14. @Override
  15. public Object next() {
  16. if(pos<collection.size()-1){
  17. pos++;
  18. }
  19. return collection.get(pos);
  20. }
  21. @Override
  22. public boolean hasNext() {
  23. if(pos<collection.size()-1){
  24. return true;
  25. }else{
  26. return false;
  27. }
  28. }
  29. @Override
  30. public Object first() {
  31. pos = 0;
  32. return collection.get(pos);
  33. }
  34. }

测试类:

[java] view plaincopy
  1. public class Test {
  2. public static void main(String[] args) {
  3. Collection collection = new MyCollection();
  4. Iterator it = collection.iterator();
  5. while(it.hasNext()){
  6. System.out.println(it.next());
  7. }
  8. }
  9. }

输出:A B C D E

此处我们貌似模拟了一个集合类的过程,感觉是不是很爽?其实JDK中各个类也都是这些基本的东西,加一些设计模式,再加一些优化放到一起的,只要我们把这些东西学会了,掌握好了,我们也可以写出自己的集合类,甚至框架!

17、责任链模式(Chain of Responsibility)
接下来我们将要谈谈责任链模式,有多个对象,每个对象持有对下一个对象的引用,这样就会形成一条链,请求在这条链上传递,直到某一对象决定处理该请求。但是发出者并不清楚到底最终那个对象会处理该请求,所以,责任链模式可以实现,在隐瞒客户端的情况下,对系统进行动态的调整。先看看关系图:

Abstracthandler类提供了get和set方法,方便MyHandle类设置和修改引用对象,MyHandle类是核心,实例化后生成一系列相互持有的对象,构成一条链。

[java] view plaincopy
  1. public interface Handler {
  2. public void operator();
  3. }
[java] view plaincopy
  1. public abstract class AbstractHandler {
  2. private Handler handler;
  3. public Handler getHandler() {
  4. return handler;
  5. }
  6. public void setHandler(Handler handler) {
  7. this.handler = handler;
  8. }
  9. }
[java] view plaincopy
  1. public class MyHandler extends AbstractHandler implements Handler {
  2. private String name;
  3. public MyHandler(String name) {
  4. this.name = name;
  5. }
  6. @Override
  7. public void operator() {
  8. System.out.println(name+"deal!");
  9. if(getHandler()!=null){
  10. getHandler().operator();
  11. }
  12. }
  13. }
[java] view plaincopy
  1. public class Test {
  2. public static void main(String[] args) {
  3. MyHandler h1 = new MyHandler("h1");
  4. MyHandler h2 = new MyHandler("h2");
  5. MyHandler h3 = new MyHandler("h3");
  6. h1.setHandler(h2);
  7. h2.setHandler(h3);
  8. h1.operator();
  9. }
  10. }

输出:

h1deal!
h2deal!
h3deal!

此处强调一点就是,链接上的请求可以是一条链,可以是一个树,还可以是一个环,模式本身不约束这个,需要我们自己去实现,同时,在一个时刻,命令只允许由一个对象传给另一个对象,而不允许传给多个对象。

 18、命令模式(Command)

命令模式很好理解,举个例子,司令员下令让士兵去干件事情,从整个事情的角度来考虑,司令员的作用是,发出口令,口令经过传递,传到了士兵耳朵里,士兵去执行。这个过程好在,三者相互解耦,任何一方都不用去依赖其他人,只需要做好自己的事儿就行,司令员要的是结果,不会去关注到底士兵是怎么实现的。我们看看关系图:

Invoker是调用者(司令员),Receiver是被调用者(士兵),MyCommand是命令,实现了Command接口,持有接收对象,看实现代码:

[java] view plaincopy
  1. public interface Command {
  2. public void exe();
  3. }
[java] view plaincopy
  1. public class MyCommand implements Command {
  2. private Receiver receiver;
  3. public MyCommand(Receiver receiver) {
  4. this.receiver = receiver;
  5. }
  6. @Override
  7. public void exe() {
  8. receiver.action();
  9. }
  10. }
[java] view plaincopy
  1. public class Receiver {
  2. public void action(){
  3. System.out.println("command received!");
  4. }
  5. }
[java] view plaincopy
  1. public class Invoker {
  2. private Command command;
  3. public Invoker(Command command) {
  4. this.command = command;
  5. }
  6. public void action(){
  7. command.exe();
  8. }
  9. }
[java] view plaincopy
  1. public class Test {
  2. public static void main(String[] args) {
  3. Receiver receiver = new Receiver();
  4. Command cmd = new MyCommand(receiver);
  5. Invoker invoker = new Invoker(cmd);
  6. invoker.action();
  7. }
  8. }

输出:command received!

这个很哈理解,命令模式的目的就是达到命令的发出者和执行者之间解耦,实现请求和执行分开,熟悉Struts的同学应该知道,Struts其实就是一种将请求和呈现分离的技术,其中必然涉及命令模式的思想!

本篇暂时就到这里,因为考虑到将来博文会不断的更新,不断的增加新内容,所以当前篇幅不易过长,以便大家阅读,所以接下来的放到另一篇里。敬请关注!

Java之美[从蛮荒到撬动地球]之设计模式三相关推荐

  1. 《国度》之大学者联盟找到了那个撬动地球的支点

    有很多人问我<国度>写了什么? 我说,这本书写的是我的志向,我的梦想,我的一个创业想法,我想要打造一个让人可以放心去相信,有乐趣,有意义,能依靠的平台,我给它取名为大学者联盟.它的基本组成 ...

  2. Java之美[从菜鸟到高手演变]系列之博文阅读导航

    随着博文越来越多,为博客添加一个导航很有必要!本博客将相继开通Java.CloudFoundry.Linux.Ruby等专栏,都会设立目录,希望读者朋友们能更加方便的阅读! 在阅读的过程中有任何问题, ...

  3. 给我一个兴趣点,我就能撬动一个行业

    给我一个兴趣点,我就能撬动一个行业 兴趣是什么?据百度百科解释:兴趣指 兴致,对事物喜好或关切的情绪.心理学人们力求认识某种事物和从事某项活动的意识倾向.它表现为人们对某件事物.某项活动的选择性态度和 ...

  4. “P图元祖”美图秀秀,如何撬动“高颜值”年轻人口袋?

    人之爱美,是人之通性.而女人爱美,则是女人天性. 从古至今,关于女人如何变美是永恒不变的话题.在这个风口下,催生了一门又一门或长久或短暂的颜值生意. 而在互联网时代,现代女性对于美的追求更加热烈.从Q ...

  5. 如何撬动机器学习的冰山一角?

    目前,人工智能的应用日渐广泛. 而作为人工智能核心的机器学习,是一门多领域的交叉学科,专门研究计算机模拟或实现人类学习行为的方法,以获取新的知识或技能,重新组织已有的知识结构使之不断改善自身的性能. ...

  6. 京东11·11:撬动数据中心的支点——京东阿基米德

    今年11.11,京东数据中心操作系统(JDOS)阿基米德已经全面接管了应用资源调度.每日调度百万台容器实例运转,每日为离线计算提供了多达3000万核·小时的计算资源,SLA履约率达到98.3%.在保证 ...

  7. NEC:借助AI撬动未来物联网世界

    看过<碟中谍>系列大片的朋友,可能对特工们在火车站庞大的人流中借用人脸识别隐形眼镜迅速锁定目标的场景惊叹不已,而这一幕已被NEC从梦想带到了现实.近日,NEC在东京高大上的场所--东京国际 ...

  8. 扇贝编程python是干嘛的-产品观察 | 以对话式互动学习撬动转化,扇贝编程瞄准职教市场...

    原标题:产品观察 | 以对话式互动学习撬动转化,扇贝编程瞄准职教市场 成人编程教育是职业教育行业最火热的赛道之一,除了行业内的垂直创业公司,越来越多教育公司也在把业务线延展至这一领域,以便深度结合业务 ...

  9. 【云周刊】第173期:直击数博|阿里胡晓明:用100亿的投入撬动1000亿的脱贫效应...

    2019独角兽企业重金招聘Python工程师标准>>> 本期头条 直击数博|阿里胡晓明:用100亿的投入撬动1000亿的脱贫效应  5月27日,在贵阳数博会"精准扶贫&qu ...

  10. Java之美[从菜鸟到高手演变]之Exception

    版权声明:本文为博主原创文章,未经博主允许不得转载. Exception这个东西,程序中必须会有的,尽管我们很不乐意看到它,可是从另一个角度考虑,有异常则说明程序有问题,有助于我们及时改正.有的时候程 ...

最新文章

  1. db2 springboot 整合_springboot的yml配置文件通过db2的方式整合mysql的教程
  2. 苹果7【】闪存测试软件,不厚道!iPhone7大容量版竟采用TLC闪存
  3. FTP命令行使用精粹
  4. 【MFC】自绘对话框动画效果的状态栏
  5. 界面按钮太多 聊天机器人都快被玩坏了
  6. js 获取data-属性值
  7. ncl 添加点shp文件_气象编程 | NCL高效快速精准提取不规则区域内的格点数据
  8. [UWP]了解模板化控件(4):TemplatePart
  9. 详解Javascript中的Array对象
  10. python学习之简介
  11. @order 注解用法
  12. Java进阶诀窍httpwww.china-pub.com44147
  13. 由于找不到MSVCR110.dll,无法继续执行代码........启动的解决方法
  14. IE浏览器页面卡死问题
  15. arcgis字段计算器赋值_【干货】关于ArcGIS的这62个常用技巧,你造吗?
  16. Android屏幕适配全攻略3-和产品经理聊聊
  17. 思维导图如何助力营销策划
  18. USACO——Mixing Milk 混合牛奶
  19. apiserver 补充 限流认证 以及mutating流程
  20. 基于spring boot 的学生科研项目共享平台毕业设计源码271611

热门文章

  1. 推荐系统的几种常用算法总结
  2. 【docker】ffmpeg本地转码三路推srs
  3. win10平板续航测试软件,Win10 S版Surface Pro 4续航测试
  4. IDEA jsp页面代码没有高亮
  5. 计算机用户要以ADSL,建设项目进度控制超星尔雅期末答案
  6. 被裁员工公开呛声IBM人工智能,有双好鞋却不知怎么走路
  7. Unity2017安装
  8. Hadoop虚拟机镜像
  9. 海信电视 LED55K370 升级固件总结【含固件下载地址】
  10. 解决“配置系统未能初始化”问题