天天看点

扩展类的三种方式(继承,装饰模式,动态代理)一、说明二、基础接口和类三、扩展的三种方式四、三种方式说明

扩展类的三种方式(继承,装饰模式,动态代理)

一、说明

扩展类的三种方式:

【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;

              }         

       });