JavaWeb學習之設計模式
阿新 • • 發佈:2020-08-05
一、單例模式:只有一個例項的物件
程式碼:
public class SingleTemp{ private SingleTemp(){ } public static SingleTemp single = new SingleTemp(); public static SingleTemp getInstance(){ return single; } }
二、裝飾者模式:增強原始程式碼的功能,在不改動原始程式碼的基礎上
繼承也可以實現
原始程式碼:
public interface ICar { public void start(); public void run(); public void stop(); } public class GoogleCar implements ICar{ @Override public void start(){ ... } @Override public void run(){ ... } @Override public void stop(){ ... } }
繼承程式碼:
public class MyCar extends GoogleCar{ @Override public void start(){ //增強程式碼.... super.start(); //增強程式碼.... } } public class Test{ public static void main(String[] args){ ICar car=new MyCar(); car.start(); } }
很完美的實現我們想要的增強功能,且沒有改動原始碼。但是很多時候原始碼(原始碼被final修飾)是不允許繼承的話,繼承就不能實現了。
這就要用到裝飾者模式
裝飾者模式的場景:無法獲取原始碼,無法使用繼承,要增強已經存在物件上的功能
前提:可以獲取到被裝飾的物件(GoogleCar)實現的所有介面(ICar)
程式碼:
public final class GoogleCar implements ICar{ @Override public void start(){ ... } @Override public void run(){ ... } @Override public void stop(){ ... } }public class MyCar implements ICar{ ICar car; public MyCar(ICar car){ this.car=car; } @Override public void start(){ //增強程式碼.... this.car.start(); //增強程式碼.... } @Override public void run(){ //增強程式碼.... this.car.run() //增強程式碼.... } @Override public void stop(){ this.car.stop() } } public class Test{ public static void main(String[] args){ ICar car=new MyCar(new GoogleCar()); car.start(); } }
弊端:如果被實現的介面中的方法過多,裝飾類中的方法就會冗餘,一些不需要增強的方法需要重寫其方法
三、動態代理(Proxy.newProxyInstance)
原理:通過虛擬機器在記憶體中建立位元組碼檔案
1、通過虛擬機器在記憶體中建立位元組碼檔案,位元組碼檔案的內容是:增強功能的類中的所有方法(是指類實現的所有介面中的方法,不包含類自身的方法)
2、通過字節碼載入器把字虛擬機器在記憶體中建立的節碼檔案載入成位元組碼物件
3、虛擬機器修改記憶體中的位元組碼物件中的方法具體處理
具體程式碼如下:
public class Test{ public static void main(String[] args){ //1.根據GoogleCar位元組碼檔案獲取其實現的所有介面 //2.獲取介面中所有的方法 /* Class[] clazz=GoogleCar.class.getInterfaces(); for(Class cla : clazz){ Method[] mds= cla.getMethods(); for(Method method : mds){ method.getName(); } } */ /* 引數1:固定值(位元組碼載入器載入記憶體中位元組碼檔案,建立位元組碼物件) 引數2:建立位元組碼物件中有哪些介面 引數3:建立位元組碼物件中介面的方法的具體處理 */ ICar car = (ICar)Proxy.newProxyInstance(Test.class.getClassLoader,GoogleCar.class.getInterfaces() ,new InvocationHandler(){ /* method:正在執行的方法 args:正在執行的方法中的引數 Object:方法執行後的返回值 */ @Override public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{ Object obj = null; if(method.getName().equalsIgnoreCase("start")){ //增強程式碼...... } // 執行當前方法 obj = method.invoke(new GoogleCar(),args); return obj; } }); car.start(); car.run(); car.stop(); } }