通过Java的继承与聚合两种形式实现静态代理

运用场景:

当需要调用到某个方法,而又需要在该方法执行之前或之后再执行其他的逻辑时,就可以用到代理的技术。

分类:

代理分为静态代理和动态代理两种。

可以通过两种方式来实现静态代理,一种是继承的方式,另一种是聚合的方式。

代码演示:

假设汽车有run(行驶)和stop(停止)两个功能,通过一个CarInterface接口来表示

package cn.jie.util;

public interface CarInterface {
	//卡车有行驶功能
	public void run();
	//卡车有停止功能
	public void stop();
}

产生一辆汽车,实现该接口表示具备了行驶和停车两项功能

package cn.jie.util;

//实现接口,代表具备了两项功能
public class Car implements CarInterface{
	
	//车辆行驶功能,实现行驶的逻辑
	public  void  run()
	{
		System.out.println("车开动了!");
	}
	//车辆停车功能,实现停车的逻辑
	public void  stop()
	{
		System.out.println("车停下了!");
	}

}

但是,我们通常行驶汽车时,需要先让汽车动起来,车才能行驶;而要让车停下来,也需要先减速。

也就是说我们在调用run方法前需要先执行给车加速的逻辑,同样,在调用stop方法前需要执行给车减速的逻辑,这样才能实现汽车驾驶的完整动作。这种情况下就可以运用到静态代理的技术。静态代理又可以通过继承和聚合两种方式来实现。

继承方式:

先产生一个汽车的代理类CarProxy,让它去继承父类Car,这样这个代理类就拥有与父类一样的run方法和stop方法,此时就可以通过覆写父类方法的方式来插入我们要执行的逻辑。

package cn.jie.util;

public class CarProxy extends Car{
	
	public void run()
	{
		//给汽车加速的逻辑
		System.out.println("车加速!");
		super.run();
	}
	
	public void stop()
	{
		//给汽车减速的逻辑
		System.out.println("车减速!");
		super.stop();
	}
	
}

测试汽车驾驶

由于CarProxy继承自Car类,所以我们可以通过Car类向上转型得到代理类对象,从而调用方法

package cn.jie.util;

import org.junit.Test;

public class TestCar {
        
	@Test
	public void testDrive()
	{
		//通过继承方式
		Car car=new CarProxy();
		car.run();
		car.stop();
	}
	
}

测试结果


聚合方式:

先产生一个汽车的代理类CarProxy2,让它也去实现CarInterface接口,再将Car类以成员变量的方式引入,通过构造器赋值,此时就可以在实现的接口方法中调用Car方法和插入我们要执行的逻辑。

package cn.jie.util;

public class CarProxy2 implements CarInterface{

	private Car car;
	
	public CarProxy2(Car car) {
		this.car=car;
	}
	
	@Override
	public void run() {
		//给汽车加速的逻辑
		System.out.println("车加速!");
		car.run();
	}

	@Override
	public void stop() {
		//给汽车减速的逻辑
		System.out.println("车减速!");
		car.stop();
	}

}

测试汽车驾驶

由于都是实现CarInterface接口,所以可以通过CarInterface接口对象来调用方法。

package cn.jie.util;

import org.junit.Test;

public class TestCar {

	@Test
	public void testDrive()
	{
		//通过聚合方式
		Car car=new Car();
		CarInterface proxy=new CarProxy2(car);
		proxy.run();
		proxy.stop();
	}
	
}
package cn.jie.util;
import org.junit.Test;

public class TestCar {

	@Test
	public void testDrive()
	{
	        Car car=new LabaProxy1();
		car.run();
	}
}

测试结果


继承方式与聚合方式对比:

以上的Car类称为被代理类

以上的Carproxy类和Carproxy2类都是添加了汽车速度操作的逻辑,所以可以称为汽车的速度代理类

继承方式:

如果有一个需求是在汽车加速前,按一下喇叭,也就是说需要在执行加速逻辑前再先执行一个按喇叭的逻辑,那么就需要再创建一个喇叭代理类1,去继承速度代理类,然后在调用父类run方法前添加按喇叭逻辑。

实现的逻辑顺序是:按喇叭——>加速——>行驶

package cn.jie.util;

public class LabaProxy1 extends CarProxy{
	
	public void run()
	{
		//按喇叭的逻辑
		System.out.println("按喇叭!");
		super.run();
	}
	
	public void stop()
	{
		super.stop();
	}
	
}
package cn.jie.util;
import org.junit.Test;

public class TestCar {

	@Test
	public void testDrive()
	{
	        Car car=new LabaProxy1();
		car.run();
	}
}


而如果又有一个需求是在行驶途中按喇叭,那么又需要创建一个喇叭代理类2,去继承速度代理类,然后在调用父类run方法后添加按喇叭逻辑。

实现的逻辑顺序是:加速——>行驶——>按喇叭

package cn.jie.util;

public class LabaProxy2 extends CarProxy{
	
	public void run()
	{
		//按喇叭的逻辑
		super.run();
		System.out.println("按喇叭!");
	}
	
	public void stop()
	{
		super.stop();
	}
	
}
package cn.jie.util;
import org.junit.Test;

public class TestCar {

	@Test
	public void testDrive()
	{
	        Car car=new LabaProxy2();
		car.run();
	}
}

可以看出,实现的都是三个逻辑,只是顺序发生改变,而一旦顺序改变,就需要多创建一个代理类根据顺序来调用父类的方法。当业务有很多逻辑以及顺序很复杂的时候,需要的代理类就会有很多。


聚合方式:

由于通过聚合方式实现的静态代理的代理类都是实现同一个接口, 所以可以改为用该接口即被代理类的接口来作为参数。

速度代理类的修改

package cn.jie.util;

public class CarProxy2 implements CarInterface{

	/**
	 * 由于通过聚合方式实现的静态代理都是实现同一个接口,
	 * 所以可以改为用该接口即被代理类的接口来作为参数。
	 */
	private CarInterface car;
	
	public CarProxy2(CarInterface car) {
		this.car=car;
	}
	
	@Override
	public void run() {
		//给汽车加速的逻辑
		System.out.println("车加速!");
		car.run();
	}

	@Override
	public void stop() {
		//给汽车减速的逻辑
		System.out.println("车减速!");
		car.stop();
	}

}



实现的逻辑顺序是:按喇叭——>加速——>行驶

由于新增了喇叭逻辑,所以要创建一个喇叭代理类LabaProxy3
package cn.jie.util;

public class LabaProxy3 implements CarInterface{
	
	private CarInterface car;
	
	public LabaProxy3(CarInterface car) {
		this.car=car;
	}
	
	@Override
	public void run() {
		//按喇叭的逻辑
		System.out.println("按喇叭!");
		car.run();
	}

	@Override
	public void stop() {
		car.stop();
	}

}
package cn.jie.util;

import org.junit.Test;

public class TestCar {

	@Test
	public void testDrive()
	{        
		//被代理类
		Car car=new Car();
		//速度代理类
		CarProxy2 cp=new CarProxy2(car);
		//喇叭代理类
		CarInterface proxy=new LabaProxy3(cp);
		proxy.run();
	}
	
}

测试结果





实现的逻辑顺序是:加速——>按喇叭——>行驶

只需要在测试类中更换调用顺序即可

package cn.jie.util;

import org.junit.Test;

public class TestCar {

	@Test
	public void testDrive()
	{
		//被代理类
		Car car=new Car();
		//喇叭代理类
		CarInterface proxy=new LabaProxy3(car);
		//速度代理类
		CarProxy2 cp=new CarProxy2(proxy);
		cp.run();
	}
	
}
测试结果



总结:

继承方式:每多一个逻辑,多一个代理类;逻辑顺序改变一次顺序,多一个代理类

聚合方式:每多一个逻辑,多一个代理类;逻辑顺序改变一次顺序,只需在调用时改变顺序

而且可以看到,无论是继承方式还是聚合方式,得到的代理类对象与被代理类对象不是同一个对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值