引題:假如咱們想計算一個方法的運行時間,在不動源代碼的狀況下都是用代理類來代替源碼完成業務。具體方法有下面兩種。java
源碼:dom
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:繼承方式ide
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 }
測試代碼this
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 }
總結:從上面的例子咱們能夠看出,使用集成和聚合都可以實現代理。spa
引出問題:繼承和聚合哪一種好呢?實際業務中不光有計算時間,還可能有打印日誌等(會有不少代理)。拿繼承來講,每一種咱們都須要寫一個繼承類。若是混用呢?拿計算時間和日誌來講,先時間後日志。咱們須要先寫時間繼承類,再在時間繼承類的基礎上寫日誌繼承類。若是業務反一下的話,又得重寫這兩個繼承類。這仍是隻有計算時間和打印日誌,若是須要其餘不少種代理呢?這樣顯然這樣很笨重。使用聚合能夠解決這種問題,具體以下:代理
修改計算時間的聚合代理方式,而且添加時間日誌代理,代碼以下:日誌
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 }
咱們只須要上面兩個代理類就能夠完成上面所說的全部業務。這是由於代理自己也實現了接口;測試以下code
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 }
總結:代理方式選擇了用聚合而不用繼承。blog
引出問題: