设计模式学习之代理模式学习(一)
设计模式学习之代理模式学习(一)
关于设计模式想必学习过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
设计模式学习之代理模式学习(一)相关推荐
- 设计模式 - 行为型 - 模板模式学习
现象: 设计模式 - 行为型 - 模板模式学习 介绍: 模板模式的设计思路,在抽象类中定义抽象方法的执行顺序, 并将抽象方法设定为只有子类实现,但不提供独立访问的方法 只能通过已经被安排好的定义方法去 ...
- 设计模式之静态代理模式实战
转载自 设计模式之静态代理模式实战 静态代理模式很简单,代理类和实现类都实现相同的接口,然后通过代理类来调用实现类的方法. 如我们想保存用户信息之前打印用户信息,或者保存用户信息之后把这些信息缓存下来 ...
- 《设计模式系列》- 代理模式
有情怀,有干货,微信搜索[三太子敖丙]关注这个有一点点东西的程序员. 本文 GitHub https://github.com/JavaFamily 已收录,有一线大厂面试完整考点.资料以及我的系列文 ...
- 设计模式之蝉——代理模式上中
代理模式的扩展 1 普通代理 :这种代理就是客户端只能访问代理角色,而不能访问真实角色.与设计模式之蝉--代理模式上 片基本差不多. (1)Subject抽象主题角色: (2)RealSubject具 ...
- 每日一个设计模式之【代理模式】
文章目录 每日一个设计模式之[代理模式] ☁️前言
- 设计模式之代理模式学习笔记
前言 代理模式,也叫做委托模式.就好比请律师打官司一样,为其他对象提供一种代理,来控制对这个对象的访问. 结构图 接下来我们对以上结构图拆解,进行角色分析: 1.Subject:抽象主题类,声明真实主 ...
- 设计模式学习笔记-代理模式
1. 概述 为其它对象提供一种代理以控制对这个对象的访问. 解决的问题:如果直接访问对象比较困难,或直接访问会给使用者或系统带来一系列问题.这样对于客户端(调用者)来说,就不需要直接与真实对象进行交互 ...
- 设计模式_结构型模式学习
其中,单例模式用来创建全局唯一的对象.工厂模式用来创建不同但是相关类型的对象(继承同一父类或者接口的一组子类),由给定的参数来决定创建哪种类型的对象.建造者模式是用来创建复杂对象,可以通过设置不同的可 ...
- 设计模式_行为型模式学习
我们知道,创建型设计模式主要解决"对象的创建"问题,结构型设计模式主要解决"类或对象的组合或组装"问题,那行为型设计模式主要解决的就是"类或对象之间的 ...
最新文章
- 为什么 Python 没有 main 函数?
- java concurrent包介绍及使用
- 一文搞懂 什么是CPU上下文?为什么要切换?如何减少切换?
- css中calc()方法的使用
- golang mysql封装_使用Golang 封装一个Api 框架 ----- 数据库操作篇(gorm引入)
- android 生成二维码_Java 生成二维码实战
- Flask11 Session、CSRF、注销session、利用端点自动跳转
- Redis持久化 - 邱乘屹的个人技术博客
- 64位 regsrv win10_64位WINDOWS 10系统下安装Eplan 2.8及注册过程
- React 高阶组件HOC详解
- JavaScript - PC 端通过纯 js 播放音频文件(播放提示音)
- 【loj2073】「JSOI2016」扭动的回文串(manacher+二分+双哈希)
- ARM开发基础--指令,异常源及处理过程
- 阿里云王文彬:希望云计算支撑百亿设备
- play商店 小米_Google Play 商店
- 华为5g服务器硬件供应商,华为P50系列硬件供应商名单曝光,国产化程度高,5G版或延后上市...
- datadashboard下载_Data Dashboard for LabVIEW
- echarts setoption 不生效
- 展讯mipi屏高频干扰wifi信号
- charAt()方法和charCodeAt()方法—— 从字符串中选取一个字符.