设计模式学习之代理模式学习(一)

关于设计模式想必学习过Java语言的人都知道吧,当时对其进行深入学习的的人应该不是很多。在我看来设计方面的知识相比于框架应用配置等知识要有意思的多,并且设计模式的对一个程序员的编程思想提升有着很大的帮助。但是设计模式有二十三种,想要全部掌握还是要花点时间的,但如果是只学习常用的几种设计模式还是相对容易的。下面是我学习代理模式的一些心得。

问题引出

     什么是代理模式,为什么要用代理模式。

现在有一个场景模拟:有一个tank类,他实现了Moveable接口,Moveable接口中有一个move方法,tank类重写move方法。那么现在问题来了,我要想要知道坦克move方法的执行时间怎么办。我想马上就有人会想到在move方法执行前获得一下系统时间,然后在执行后再获得一下系统时间,两个时间相减就能得到move方法的执行时间了。没错这种方法的确能解决刚刚的问题,但是同样带来了另外的问题那就是需要修改源码,这是相当不友好的,在没有源码的前提下还不能实现。那要怎么实现才比较合理了,没错就是代理。讲到这我想我不需要说代理的定义是什么了吧,请看下面代码。

Tank类的源代码:

import java.util.Random;public class Tank implements Moveable{@Overridepublic void move() {System.out.println("moving......");try {Thread.sleep(new Random().nextInt(10000));} catch (InterruptedException e) {e.printStackTrace();}}}

方法一

定义一个类继承Tank类并且重写Tank的move方法,在move方法中加入上述逻辑。

 * 方法一* @author admin**/
public class Tank2 extends Tank{@Overridepublic void move() {long start = System.currentTimeMillis();super.move();long end = System.currentTimeMillis();System.out.println("time="+(end-start));}}

方法二

定义一个Tank3类实现了Moveable接口,同时Tank3内有个Moveable类型成员变量。重写move方法并在逻辑代码中间调用Tank的move方法。具体代码如下:

/*** 方法二* @author admin**/
public class Tank3 implements Moveable{private Moveable tank;public Tank3(Moveable tank) {this.tank = tank;}@Overridepublic void move() {long start = System.currentTimeMillis();tank.move();long end = System.currentTimeMillis();System.out.println("time="+(end-start));}}

测试程序:

/*** 对于Java代理设计模式的学习* 问题:想要知道tank类中的move方法运行的时间* 方法一:编写一个类继承tank类,然后在这个类中重写move方法。加上开始时间* 和结束时间然后相减。* 方法二:编写一个类,里面有一个成员属性是tank类类型,并且实现Moveable* 接口。同样重写move方法,并在方法里调用tank中的move方法,并加上相应的* 逻辑。(常用,聚合的方式是比继承要好得多,不会出现类爆炸。)* @author admin**/
public class Client {public static void main(String[] args) {Tank2 tank = new Tank2();tank.move();Tank3 tank1 = new Tank3(new Tank());tank1.move();}}

到此两种实现方法都已给出,那么我们的任务完成了吗,还没有,既然是学习,那么我们就要深入一点。这里给出了两种实现方式,那么哪种实现方式要好了?推荐使用方法二,

我想可能很多人就不服了,为什么啊?

对于上述问题,我们再来模拟一个场景:现在我们完成计算move运行时间的逻辑,那么问题来了,你的老板要你在move方法执行前后加上一个日志操作。使用方法一就是在创建一个类继承Tank类,并重写move方法加上日志逻辑。方法二是创建一个新的类实现Moveable接口,有个成员变量是Moveable类型成员变量。重写move方法并在日志逻辑代码中间调用成员变量的move方法。这里就有人会有疑问了,感觉没区别啊,都是要创建一个新的类。是的,到现在为止表面上是没有区别。那么现在我们老板又给了我们新的要求,他要我们在实现时间计算的同时加上日志,并且是时间执行在前面,日志执行在后面。使用方法一就是再次创建一个新的类完成两次逻辑。好,老板又改主意了这次他要求日志执行在前,时间计算在后,这时你又要创建一个新的类来完成新的逻辑。哇,好麻烦啊,如果,要求的功能更多,就出现类爆炸了。

那么方法二是怎么实现的呢?

假设你现在有了时间逻辑和日志逻辑两个类,现在要完成时间加日志的组合我们只要修改Client程序就行了,不需要再创建新的类了(好舒服)

public class Client {public static void main(String[] args) {Tank tank1 = new Tank();Tank2 tank2 = new Tank2(tank1 );//使用方法二完成的时间计算的类 这里就不给出实现来了
     Tank3 tank3 = new Tank3(tank2 );//使用方法二完成的日志逻辑的类 这里就不给出实现来了
        tank3 .move();}}

应为Tank2和Tank3都实现了Movea接口,所以在创建Tank3的时候我们能把Tank2对象传进去。这样就可以把功能组合起来了。如果在创建Tank2时传Tank3就是先日志后时间。各位看都区别了吧,整整少写 了两个类。所以说哪种方式要好,相信大家已经心知肚明了吧。那么到此我们的问题解决了吧。我想说的是还没有,刚刚解决的只是各个功能之间相互组合的问题,但是我们发现每增加一个新的功能我还是要增加一个代理类,这多麻烦啊,我们能不能只生成一个,或者让程序动态的给我们生成呢?当然可以,请关注我后续的博文

设计模式学习之代理模式学习(二)—动态代理

转载于:https://www.cnblogs.com/huangliang11/p/9277923.html

设计模式学习之代理模式学习(一)相关推荐

  1. 设计模式 - 行为型 - 模板模式学习

    现象: 设计模式 - 行为型 - 模板模式学习 介绍: 模板模式的设计思路,在抽象类中定义抽象方法的执行顺序, 并将抽象方法设定为只有子类实现,但不提供独立访问的方法 只能通过已经被安排好的定义方法去 ...

  2. 设计模式之静态代理模式实战

    转载自 设计模式之静态代理模式实战 静态代理模式很简单,代理类和实现类都实现相同的接口,然后通过代理类来调用实现类的方法. 如我们想保存用户信息之前打印用户信息,或者保存用户信息之后把这些信息缓存下来 ...

  3. 《设计模式系列》- 代理模式

    有情怀,有干货,微信搜索[三太子敖丙]关注这个有一点点东西的程序员. 本文 GitHub https://github.com/JavaFamily 已收录,有一线大厂面试完整考点.资料以及我的系列文 ...

  4. 设计模式之蝉——代理模式上中

    代理模式的扩展 1 普通代理 :这种代理就是客户端只能访问代理角色,而不能访问真实角色.与设计模式之蝉--代理模式上 片基本差不多. (1)Subject抽象主题角色: (2)RealSubject具 ...

  5. 每日一个设计模式之【代理模式】

    文章目录 每日一个设计模式之[代理模式] ☁️前言

  6. 设计模式之代理模式学习笔记

    前言 代理模式,也叫做委托模式.就好比请律师打官司一样,为其他对象提供一种代理,来控制对这个对象的访问. 结构图 接下来我们对以上结构图拆解,进行角色分析: 1.Subject:抽象主题类,声明真实主 ...

  7. 设计模式学习笔记-代理模式

    1. 概述 为其它对象提供一种代理以控制对这个对象的访问. 解决的问题:如果直接访问对象比较困难,或直接访问会给使用者或系统带来一系列问题.这样对于客户端(调用者)来说,就不需要直接与真实对象进行交互 ...

  8. 设计模式_结构型模式学习

    其中,单例模式用来创建全局唯一的对象.工厂模式用来创建不同但是相关类型的对象(继承同一父类或者接口的一组子类),由给定的参数来决定创建哪种类型的对象.建造者模式是用来创建复杂对象,可以通过设置不同的可 ...

  9. 设计模式_行为型模式学习

    我们知道,创建型设计模式主要解决"对象的创建"问题,结构型设计模式主要解决"类或对象的组合或组装"问题,那行为型设计模式主要解决的就是"类或对象之间的 ...

最新文章

  1. 为什么 Python 没有 main 函数?
  2. java concurrent包介绍及使用
  3. 一文搞懂 什么是CPU上下文?为什么要切换?如何减少切换?
  4. css中calc()方法的使用
  5. golang mysql封装_使用Golang 封装一个Api 框架 ----- 数据库操作篇(gorm引入)
  6. android 生成二维码_Java 生成二维码实战
  7. Flask11 Session、CSRF、注销session、利用端点自动跳转
  8. Redis持久化 - 邱乘屹的个人技术博客
  9. 64位 regsrv win10_64位WINDOWS 10系统下安装Eplan 2.8及注册过程
  10. React 高阶组件HOC详解
  11. JavaScript - PC 端通过纯 js 播放音频文件(播放提示音)
  12. 【loj2073】「JSOI2016」扭动的回文串(manacher+二分+双哈希)
  13. ARM开发基础--指令,异常源及处理过程
  14. 阿里云王文彬:希望云计算支撑百亿设备
  15. play商店 小米_Google Play 商店
  16. 华为5g服务器硬件供应商,华为P50系列硬件供应商名单曝光,国产化程度高,5G版或延后上市...
  17. datadashboard下载_Data Dashboard for LabVIEW
  18. echarts setoption 不生效
  19. 展讯mipi屏高频干扰wifi信号
  20. charAt()方法和charCodeAt()方法—— 从字符串中选取一个字符.

热门文章

  1. 《大数据分析原理与实践》——习题
  2. 《社会智能与综合集成系统》第1章1.节参考文献
  3. returnFunc.js
  4. mongodb用户管理简单记录
  5. 如何发送Head请求
  6. 我的GitHub 欢迎光临
  7. 怎么搞技术呢?我觉得最简单的方法
  8. ae这样设置导出比较快 480p比较适合快速看看demo的样子,注意tradeoff
  9. use stacks能够把很多相似的文件叠加在macos的桌面上
  10. 关于投资银行和咨询的理解和感悟