代理
引题:假如我们想计算一个方法的运行时间,在不动源代码的情况下都是用代理类来代替源码完成业务。具体方法有下面两种。
源码:
1 package com.liuzhihong.inter; 2 /** 3 * @ClassName Moveable 4 * @Description 5 * @Author 刘志红 6 * @Date 2019/4/3 7 **/ 8 public interface Moveable { 9 void move(); 10 }
1 package com.liuzhihong.waitproxy; 2 import com.liuzhihong.inter.Moveable; 3 /** 4 * @ClassName Person 5 * @Description 6 * @Author 刘志红 7 * @Date 2019/4/3 8 **/ 9 public class Person implements Moveable { 10 @Override 11 public void move() { 12 System.out.println("Person.move"); 13 try { 14 Thread.sleep((int) (Math.random() * 10000)); 15 } catch (InterruptedException e) { 16 e.printStackTrace(); 17 } 18 } 19 }
1:继承方式
1 package com.liuzhihong.ext; 2 import com.liuzhihong.waitproxy.Person; 3 4 import java.time.Duration; 5 import java.time.Instant; 6 /** 7 * @ClassName PersonExtend 8 * @Description 9 * @Author 刘志红 10 * @Date 2019/4/3 11 **/ 12 public class PersonExtend extends Person { 13 @Override 14 public void move() { 15 Instant start = Instant.now(); 16 super.move(); 17 Instant end = Instant.now(); 18 System.out.println("运行时间"+ Duration.between(start,end).toMillis()); 19 } 20 }
2:聚合方式
1 package com.liuzhihong.polymerization; 2 import com.liuzhihong.inter.Moveable; 3 import com.liuzhihong.waitproxy.Person; 4 5 import java.time.Duration; 6 import java.time.Instant; 7 /** 8 * @ClassName PersonPol 9 * @Description 10 * @Author 刘志红 11 * @Date 2019/4/3 12 **/ 13 public class PersonPol implements Moveable { 14 private Person person; 15 public PersonPol(Person person) { 16 this.person = person; 17 } 18 @Override 19 public void move() { 20 Instant start = Instant.now(); 21 person.move(); 22 Instant end = Instant.now(); 23 System.out.println("Program RunningTime:"+ Duration.between(start, end).toMillis()); 24 } 25 }
测试代码
1 package com.liuzhihong.test; 2 import com.liuzhihong.ext.PersonExtend; 3 import com.liuzhihong.polymerization.PersonPol; 4 import com.liuzhihong.waitproxy.Person; 5 import org.junit.Test; 6 /** 7 * @ClassName Test 8 * @Description 9 * @Author 刘志红 10 * @Date 2019/4/3 11 **/ 12 public class TestProxy { 13 @Test 14 public void testEXC(){ 15 new PersonExtend().move(); 16 } 17 18 @Test 19 public void testPlo(){ 20 new PersonPol(new Person()).move(); 21 } 22 }
总结:从上面的例子我们可以看出,使用集成和聚合都能够实现代理。
引出问题:继承和聚合哪种好呢?实际业务中不光有计算时间,还可能有打印日志等(会有很多代理)。拿继承来说,每一种我们都需要写一个继承类。如果混用呢?拿计算时间和日志来说,先时间后日志。我们需要先写时间继承类,再在时间继承类的基础上写日志继承类。如果业务反一下的话,又得重写这两个继承类。这还是只有计算时间和打印日志,如果需要其他很多种代理呢?这样显然这样很笨重。使用聚合可以解决这种问题,具体如下:
修改计算时间的聚合代理方式,并且添加时间日志代理,代码如下:
1 package com.liuzhihong.polymerization; 2 import com.liuzhihong.inter.Moveable; 3 import com.liuzhihong.waitproxy.Person; 4 5 import java.time.Duration; 6 import java.time.Instant; 7 /** 8 * @ClassName PersonPol 9 * @Description 10 * @Author 刘志红 11 * @Date 2019/4/3 12 **/ 13 public class TimeProxy implements Moveable { 14 private Moveable moveable; 15 public TimeProxy(Moveable moveable) { 16 this.moveable = moveable; 17 } 18 @Override 19 public void move() { 20 Instant start = Instant.now(); 21 moveable.move(); 22 Instant end = Instant.now(); 23 System.out.println("Program RunningTime:" + Duration.between(start, end).toMillis()); 24 } 25 }
1 package com.liuzhihong.polymerization; 2 import com.liuzhihong.inter.Moveable; 3 /** 4 * @ClassName LogProxy 5 * @Description 6 * @Author 刘志红 7 * @Date 2019/4/3 8 **/ 9 public class LogProxy implements Moveable { 10 private Moveable moveable; 11 public LogProxy(Moveable moveable) { 12 this.moveable = moveable; 13 } 14 @Override 15 public void move() { 16 System.out.println("method begin..."); 17 moveable.move(); 18 System.out.println("method end!!!"); 19 } 20 }
我们只需要上面两个代理类就可以完成上面所说的所有业务。这是因为代理本身也实现了接口;测试如下
1 package com.liuzhihong.test; 2 import com.liuzhihong.polymerization.LogProxy; 3 import com.liuzhihong.polymerization.TimeProxy; 4 import com.liuzhihong.waitproxy.Person; 5 import org.junit.Test; 6 /** 7 * @ClassName Test 8 * @Description 9 * @Author 刘志红 10 * @Date 2019/4/3 11 **/ 12 public class TestProxy { 13 /** 14 * 计算时间 15 */ 16 @Test 17 public void testTime() { 18 new TimeProxy(new Person()).move(); 19 } 20 /** 21 * 加日志 22 */ 23 @Test 24 public void testLog() { 25 new LogProxy(new Person()).move(); 26 } 27 /** 28 * 日志包计算时间 29 */ 30 @Test 31 public void testTimeLog() { 32 new LogProxy(new TimeProxy(new Person())).move(); 33 } 34 /** 35 * 计算时间包日志 36 */ 37 @Test 38 public void testLogTime() { 39 new TimeProxy(new LogProxy(new Person())).move(); 40 } 41 }
总结:代理方式选择了用聚合而不用继承。
引出问题:
作者:刘志红
-------------------------------------------
个性签名:独学而无友,则孤陋而寡闻。做一个灵魂有趣的人!
如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!