天天看點

擴充類的三種方式(繼承,裝飾模式,動态代理)一、說明二、基礎接口和類三、擴充的三種方式四、三種方式說明

擴充類的三種方式(繼承,裝飾模式,動态代理)

一、說明

擴充類的三種方式:

【1】基于繼承--- 方法覆寫

【2】使用裝飾模式包裝類,增強原有行為

【3】使用動态代理--- 基于位元組碼Class在記憶體中執行過程

二、基礎接口和類

(1)貓接口

interface ICat{
    public void run();
}
           

(2)普通貓類

//貓類,實作ICat接口【基礎類】
class Cat implements ICat{
    @Override
    public void run() {
       System.out.println("貓捉了一隻老鼠...");
    }
}
           

三、擴充的三種方式

1、基于繼承--- 方法覆寫

(1)代碼:

package proxy;
//1.繼承--匿名内部類測試
public class InheritMethod {

	public static void main(String[] args) {
		Cat cat=new Cat(){
			@Override
			public void run(){
				//加強的内容... 
				System.out.println("貓的奔跑的速度 為 25m/s...");
				super.run();
			}
		};
		cat.run();//調用加強後的方法

	}
}
           

(2)結果:

貓的奔跑的速度 為 25m/s...

貓捉了 一隻 老鼠...

2、使用裝飾模式包裝類,增強原有行為

(1)代碼:

【1】裝飾類

package proxy;

//裝飾類【加強類】
//對被裝飾類的方法進行加強
//用的時候, 要滿足的條件:

/*裝飾設計模式 :   裝飾者 和 被裝飾者
*用的時候, 要滿足兩個條件:
*第一個:裝飾者和被裝飾者 必須要實作同樣的接口或者 有共同 父類 
*第二個:被裝飾者 必須要 傳遞給 裝飾者,即:裝飾者持有 對被裝飾者的引用
*/
public class DecratorCat implements ICat{
	private ICat cat;//被裝飾者
	public DecratorCat(ICat cat){
		this.cat=cat;
	}
	@Override
	public void run() {
		//添加加強的内容
		System.out.println("貓捉住了老鼠隻用了3秒的時間");
		//調用 原有的方法
		cat.run();
	}
	
}
           

【2】加強測試類

package proxy;

//2.裝飾者設計模式測試
public class DecratorCatTest {
	public static void main(String[] args) {

		ICat cat=new Cat();//原來的貓
		DecratorCat decratorCat=new DecratorCat(cat);//被裝飾後的貓
		decratorCat.run();

	}

}
           

(2)結果:

貓捉住了老鼠隻用了3秒的時間

貓捉了 一隻 老鼠...

3、使用動态代理--- 基于位元組碼Class在記憶體中執行過程

(1)代碼:

package proxy;


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import org.junit.Test;

public class MethodEnhancement {

	//3.動态代理
	//代理模式:給某一個對象提供一個代理,并由代理對象控制對原對象的引用。
	//這個代理可以對源對象的一些方法進行加強處理
	//Porxy類
	//代理對象的産生:static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
	@Test
	public void test3(){
		final ICat cat=new Cat();//要代理的貓對象【代理】
		//Object obj=Proxy.newProxyInstance(loader, interfaces, h)
		
		ClassLoader loader = MethodEnhancement.class.getClassLoader();
		Class<?>[] interfaces = cat.getClass().getInterfaces();
		//代理貓對象
		//loader:任意的類加載器都行
		//interfaces:要的是真是的要産生是哪個類的代理對象
		ICat proxyCat=(ICat)Proxy.newProxyInstance(loader, interfaces, new InvocationHandler(){

			/*解釋:本代碼作用---調用了,代理對象的一個方法,其中:方法裡面的參數是什麼也在這裡說明了
			 * 
			 * @param proxy---代理對象
			 * @param method---調用的方法的對象(将調用方法當作一個method對象傳遞進來)
			 * @param args---将調用方法的時候,傳遞的參數封裝到一個Object[]中傳遞進來
			 * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
			 */
			
			//當調用代理貓:ProxyCat的任何方法時,都會進入這裡執行相應的代碼
			//這裡的相應代碼指的是:Cat對象裡面的方法
			//言外之意:ProxyCat(代理貓)具備Cat(普通貓)的所有方法,但是代理貓可以在
			//原來的相應方法上做增強操作!或者不做任何操作--代碼:method.invoke(cat, args)
			//不做任何操作,就是調用Cat對象的某個方法method,其中裡面的參數情況為Object[] args--》mehtod.invoke(cat,args)
			
			@Override
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				
				//當調用了代理對象ProxyCat的run()方法時,執行此段代碼
				if(method.getName().equals("run")){
					
					//結果:加強run方法+原有run方法
					
					//加強原來的run方法
					System.out.println("代理加強————————————————————————");
						System.out.println("這貓的奔跑速度果然是非常好啊");
					//調用原來的run方法
					return method.invoke(cat, args);//cat對象的原有的方法
				}
				else{
					System.out.println("方法名:"+method.getName());
					//當代理貓(ProxyCat)調用普通貓(Cat)的除了run方法以外的方法時,直接傳回普通貓的該方法
					return method.invoke(cat, args);//cat對象的原有的方法
				}
				
//				//當代理貓(ProxyCat)調用普通貓(Cat)的除了run方法以外的方法時,直接傳回普通貓的該方法
//				return method.invoke(cat, args);//cat對象的原有的方法
			}
			
		});
		//關鍵點:
		//當ProxyCat代理貓,調用了代理對象【代理對象:Cat】的任何的方法的時候, 都會 執行 invoke方法裡的邏輯 
		
		//ProxyCat代理貓
		proxyCat.run();//代理貓調用了run方法
		
		proxyCat.hashCode();//代理貓調用了hashCode方法
		proxyCat.toString();//代理貓調用了toString方法
		
	}
}
           

(2)結果:

代理加強————————————————————————

這貓的奔跑速度果然是非常好啊

貓捉了 一隻 老鼠...

方法名:hashCode

方法名:toString

四、三種方式說明

(1)基于繼承--- 方法覆寫

         繼承父類方法,然後在父類的方法上進行擴充操作

(2)使用裝飾模式包裝類,增強原有行為

裝飾類【加強類】--對被裝飾類的方法進行加強

裝飾設計模式:裝飾者 和 被裝飾者

用的時候, 要滿足兩個條件:

第一個:裝飾者和被裝飾者 必須要實作同樣的接口或者有共同父類

第二個:被裝飾者必須要傳遞給裝飾者,即:裝飾者持有對被裝飾者的引用

(3)使用動态代理--- 基于位元組碼Class在記憶體中執行過程

【1】說明

代理模式:給某一個對象提供一個代理,并由代理對象控制對原對象的引用。

作用:這個代理可以對源對象的一些方法進行加強處理

【2】使用

Proxy類

代理對象的産生:

static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces, InvocationHandler h)

參數說明:

loader:任意的類加載器都行

interfaces:要的是真是的要産生是哪個類的代理對象

InvocationHandler:裡面覆寫方法 public Object invoke(Objectproxy, Methodmethod, Object[]args)

代理方法的增強:(去裡面寫相關的代碼即可)

publicObject invoke(Objectproxy, Methodmethod, Object[]args)

                  throws Throwable {

                     returnnull;

              }         

       });

比如:

ICat proxyCat=(ICat)Proxy.newProxyInstance(loader,interfaces,new InvocationHandler(){

@Override

*解釋:本代碼作用---調用了,代理對象的一個方法,其中:方法裡面的參數是什麼也在這裡說明了

*@param proxy---代理對象

*@param method---調用的方法的對象(将調用方法當作一個method對象傳遞進來)

*@param args---将調用方法的時候,傳遞的參數封裝到一個Object[]中傳遞進來

publicObject invoke(Objectproxy, Methodmethod, Object[]args)

                  throws Throwable {

                     returnnull;

              }         

       });