设计模式学习之代理模式学习(一)
設(shè)計模式學(xué)習(xí)之代理模式學(xué)習(xí)(一)
? ? ? 關(guān)于設(shè)計模式想必學(xué)習(xí)過Java語言的人都知道吧,當(dāng)時對其進行深入學(xué)習(xí)的的人應(yīng)該不是很多。在我看來設(shè)計方面的知識相比于框架應(yīng)用配置等知識要有意思的多,并且設(shè)計模式的對一個程序員的編程思想提升有著很大的幫助。但是設(shè)計模式有二十三種,想要全部掌握還是要花點時間的,但如果是只學(xué)習(xí)常用的幾種設(shè)計模式還是相對容易的。下面是我學(xué)習(xí)代理模式的一些心得。
問題引出
? ?? 什么是代理模式,為什么要用代理模式。
? ? ? 現(xiàn)在有一個場景模擬:有一個tank類,他實現(xiàn)了Moveable接口,Moveable接口中有一個move方法,tank類重寫move方法。那么現(xiàn)在問題來了,我要想要知道坦克move方法的執(zhí)行時間怎么辦。我想馬上就有人會想到在move方法執(zhí)行前獲得一下系統(tǒng)時間,然后在執(zhí)行后再獲得一下系統(tǒng)時間,兩個時間相減就能得到move方法的執(zhí)行時間了。沒錯這種方法的確能解決剛剛的問題,但是同樣帶來了另外的問題那就是需要修改源碼,這是相當(dāng)不友好的,在沒有源碼的前提下還不能實現(xiàn)。那要怎么實現(xiàn)才比較合理了,沒錯就是代理。講到這我想我不需要說代理的定義是什么了吧,請看下面代碼。
?
?
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類實現(xiàn)了Moveable接口,同時Tank3內(nèi)有個Moveable類型成員變量。重寫move方法并在邏輯代碼中間調(diào)用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代理設(shè)計模式的學(xué)習(xí)* 問題:想要知道tank類中的move方法運行的時間* 方法一:編寫一個類繼承tank類,然后在這個類中重寫move方法。加上開始時間* 和結(jié)束時間然后相減。* 方法二:編寫一個類,里面有一個成員屬性是tank類類型,并且實現(xiàn)Moveable* 接口。同樣重寫move方法,并在方法里調(diào)用tank中的move方法,并加上相應(yīng)的* 邏輯。(常用,聚合的方式是比繼承要好得多,不會出現(xiàn)類爆炸。)* @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();}}?
?
? ?到此兩種實現(xiàn)方法都已給出,那么我們的任務(wù)完成了嗎,還沒有,既然是學(xué)習(xí),那么我們就要深入一點。這里給出了兩種實現(xiàn)方式,那么哪種實現(xiàn)方式要好了?推薦使用方法二,
我想可能很多人就不服了,為什么啊?
? ? 對于上述問題,我們再來模擬一個場景:現(xiàn)在我們完成計算move運行時間的邏輯,那么問題來了,你的老板要你在move方法執(zhí)行前后加上一個日志操作。使用方法一就是在創(chuàng)建一個類繼承Tank類,并重寫move方法加上日志邏輯。方法二是創(chuàng)建一個新的類實現(xiàn)Moveable接口,有個成員變量是Moveable類型成員變量。重寫move方法并在日志邏輯代碼中間調(diào)用成員變量的move方法。這里就有人會有疑問了,感覺沒區(qū)別啊,都是要創(chuàng)建一個新的類。是的,到現(xiàn)在為止表面上是沒有區(qū)別。那么現(xiàn)在我們老板又給了我們新的要求,他要我們在實現(xiàn)時間計算的同時加上日志,并且是時間執(zhí)行在前面,日志執(zhí)行在后面。使用方法一就是再次創(chuàng)建一個新的類完成兩次邏輯。好,老板又改主意了這次他要求日志執(zhí)行在前,時間計算在后,這時你又要創(chuàng)建一個新的類來完成新的邏輯。哇,好麻煩啊,如果,要求的功能更多,就出現(xiàn)類爆炸了。
? ?那么方法二是怎么實現(xiàn)的呢?
? ? 假設(shè)你現(xiàn)在有了時間邏輯和日志邏輯兩個類,現(xiàn)在要完成時間加日志的組合我們只要修改Client程序就行了,不需要再創(chuàng)建新的類了(好舒服)
public class Client {public static void main(String[] args) {Tank tank1 = new Tank();Tank2 tank2 = new Tank2(tank1 );//使用方法二完成的時間計算的類 這里就不給出實現(xiàn)來了 Tank3 tank3 = new Tank3(tank2 );//使用方法二完成的日志邏輯的類 這里就不給出實現(xiàn)來了 tank3 .move();}}? ?應(yīng)為Tank2和Tank3都實現(xiàn)了Movea接口,所以在創(chuàng)建Tank3的時候我們能把Tank2對象傳進去。這樣就可以把功能組合起來了。如果在創(chuàng)建Tank2時傳Tank3就是先日志后時間。各位看都區(qū)別了吧,整整少寫 了兩個類。所以說哪種方式要好,相信大家已經(jīng)心知肚明了吧。那么到此我們的問題解決了吧。我想說的是還沒有,剛剛解決的只是各個功能之間相互組合的問題,但是我們發(fā)現(xiàn)每增加一個新的功能我還是要增加一個代理類,這多麻煩啊,我們能不能只生成一個,或者讓程序動態(tài)的給我們生成呢?當(dāng)然可以,請關(guān)注我后續(xù)的博文
設(shè)計模式學(xué)習(xí)之代理模式學(xué)習(xí)(二)—動態(tài)代理
?
轉(zhuǎn)載于:https://www.cnblogs.com/huangliang11/p/9277923.html
與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的设计模式学习之代理模式学习(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Unicode-objects must
- 下一篇: WPF特效-拼图游戏