1. 程式人生 > >Java設計模式---《裝飾模式&&代理模式》

Java設計模式---《裝飾模式&&代理模式》

物件增強常用的三種方式:

  • 繼承
  • 裝飾
  • 代理

最簡單的方式就是繼承父類,子類擴充套件來達到目的。雖然簡單,但是這種方式的缺陷非常大

 裝飾模式:

 

  • 一、如果父類是帶有資料、資訊、屬性的話,那麼子類無法增強。
  • 二、子類實現了之後需求無法變更,增強的內容是固定的。

場景:二次開發的時候,無法獲取到原始碼,無法使用繼承前提下,要對已經存在物件上的功能進行增強.

 前提: 可以獲取到被裝飾的物件GoogleCar實現的所有介面

 實現思路: 自定定義裝飾類實現ICar介面,為自定義裝飾類傳遞被裝飾的物件

弊端:如果被實現的介面中的方法過多,裝飾類中的方法過多冗餘

 Google汽車案例:

【/SingleInstance/it.cast.single.demo】

Icar介面汽車製造標準 : Icar

public interface Icar {
	void start();
	void run();
	void stop();
}

谷歌汽車,實現了Icar介面:GoogleCar

public class GoogleCar implements Icar {

	@Override
	public void start() {
		// TODO Auto-generated method stub
		System.out.println("Google start...");
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		System.out.println("Google run...");

	}

	@Override
	public void stop() {
		// TODO Auto-generated method stub
		System.out.println("Google stop...");
	}
}

GoogleCar的裝飾類,同樣實現了Icar介面,定義了以介面為引數的建構函式,增強了GoogleCar的方法:MycarWraper

public class MycarWraper implements Icar {
	private Icar car;
	
	public MycarWraper(Icar car) {
		super();
		this.car = car;
	}

	@Override
	public void start() {
		// TODO Auto-generated method stub
		System.out.println("檢查天氣是否良好。。。");
		car.start();
		System.out.println("檢查路況是否良好。。。");
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		car.run();
	}

	@Override
	public void stop() {
		// TODO Auto-generated method stub
		car.stop();
	}
}

測試裝飾著模式:TestDemo

public class TestDemo {
	@Test
	public void testCar() {
		//把GoogleCar傳進去
		Icar icar=new MycarWraper(new GoogleCar());
		icar.start();
		icar.run();
		icar.stop();
	}
}

動態代理:通過建立指定的位元組碼檔案來解決裝飾著模式的弊端

Icar介面汽車製造標準 ,給start方法增加了引數和返回值: Icar

public interface Icar {
	String start(int a,int b);
	void run();
	void stop();
}

谷歌汽車,實現了Icar介面:

public class GoogleCar implements Icar {

	@Override
	public String start(int a,int b) {
		System.out.println("Google start...");
		return a+b+"Google";
	}

	@Override
	public void run() {
		System.out.println("Google run...");

	}

	@Override
	public void stop() {
		System.out.println("Google stop...");
	}
}

測試getInterfaces方法:獲取一個類上的介面:TestMethod

public class TestMethod {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//獲取GoogleCar類上的介面
		Class[] interfaces = GoogleCar.class.getInterfaces();
		//因為GoogleCar上只有一個介面,所以取陣列的第一個值獲得icar介面
		Class icar=interfaces[0];
		//獲取Icr接口裡面的方法
		Method[] methods = icar.getMethods();
		for (Method method : methods) {
			//列印方法名
			System.out.println(method.getName());
		}
	}
}

測試動態代理:TestCar

public abstract class TestCar {

	public static void main(String[] args) {
		
		//1param: 固定值: 告訴虛擬機器用哪個位元組碼載入器載入記憶體中創建出的位元組碼檔案,一般用本類的載入器
		//2param: 告訴虛擬機器記憶體中正在被建立的位元組碼檔案中應該有哪些方法
		//3param: 告訴虛擬機器正在被建立的位元組碼上的各個方法如何處理
		Icar car=(Icar)Proxy.newProxyInstance(TestCar.class.getClassLoader(), GoogleCar.class.getInterfaces(),new InvocationHandler() {

			//method:代表正在執行的方法
			//args:代表正在執行的方法中的引數
			//Object:代表方法執行完畢之後的返回值
			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				//執行當前的方法
				//method.invoke(new GoogleCar(), args);
				
				//執行方法返回的結果
				Object rs=null;
				if (method.getName().equalsIgnoreCase("start")) {
					System.out.println("檢查天氣是否良好。。。");
					//列印start方法的引數
					System.out.println(Arrays.toString(args));
					
					rs=method.invoke(new GoogleCar(), args);
					System.out.println("檢查路況是否良好。。。");
				} else {
					rs=method.invoke(new GoogleCar(), args);
				}
				return rs;public abstract class TestCar {

	public static void main(String[] args) {
		
		//1param: 固定值: 告訴虛擬機器用哪個位元組碼載入器載入記憶體中創建出的位元組碼檔案,一般用本類的載入器
		//2param: 告訴虛擬機器記憶體中正在被建立的位元組碼檔案中應該有哪些方法
		//3param: 告訴虛擬機器正在被建立的位元組碼上的各個方法如何處理
		Icar car=(Icar)Proxy.newProxyInstance(TestCar.class.getClassLoader(), GoogleCar.class.getInterfaces(),new InvocationHandler() {

			//method:代表正在執行的方法
			//args:代表正在執行的方法中的引數
			//Object:代表方法執行完畢之後的返回值
			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				//執行當前的方法
				//method.invoke(new GoogleCar(), args);
				
				//執行方法返回的結果
				Object rs=null;
				if (method.getName().equalsIgnoreCase("start")) {
					System.out.println("檢查天氣是否良好。。。");
					//列印start方法的引數
					System.out.println(Arrays.toString(args));
					
					rs=method.invoke(new GoogleCar(), args);
					System.out.println("檢查路況是否良好。。。");
				} else {
					rs=method.invoke(new GoogleCar(), args);
				}
				return rs;
			}
		});
		//執行的是上面建立的位元組碼檔案的方法
		String rs=car.start(250,520);
		System.out.println(rs);
		car.run();
		car.stop();
	}
}
			}
		});
		//執行的是上面建立的位元組碼檔案的方法
		String rs=car.start(250,520);
		System.out.println(rs);
		car.run();
		car.stop();
	}
}