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();
	}
}

猜你喜欢

转载自blog.csdn.net/TDOA1024/article/details/85226624