Java基础之设计模式

设计模式在Java中非常重要,在此把Animal接口和Dog类(实现Animal接口)作为基准,分别写出用装饰者模式、静态代理模式和动态代理模式改造say方法的代码,为了和这三种模式写出的代码比较,先写一个熟悉的继承Dog类的代码,所有代码和运行结果如下所示:
1、Animal接口:

package com.huanletao.test;

public interface Animal {
     //定义吃方法
	public void eat();
	//定义说方法
	public void say();
}

2、Dog类

package com.huanletao.test;

public class Dog implements Animal {
	@Override
	public void eat() {
		System.out.println("狗在么么么地吃");
	}
	@Override
	public void say() {
		System.out.println("狗在汪汪汪地叫");	
	}
	//再重新写一个睡觉的方法
	public void sleep(){
		System.out.println("狗在睡觉......");
	}
}

3、继承

package com.huanletao.test;

public class Dog_extends extends Dog {
	@Override
	public void say() {
		System.out.println("狗在喵喵喵地叫");
	}
}

4、装饰者模式

package com.huanletao.test;

public class Dog_ZS implements Animal {
	// 装饰者首先实现和被装饰者同一个接口,然后弄一个有参构造,把对象放进去
	// 接口不是创建对象没有意义吗?这里只是声明从而统一类型,并没有创建?private这一行只是故意设定一个对象,体现装饰者作用。
	// 不,是为了this.ani=ani用的。
	private Animal ani = null;
	public Dog_ZS(Animal ani) {
		this.ani = ani;
	}
	@Override
	public void eat() {
		ani.eat();
	}
	@Override
	public void say() {
		System.out.println("狗在没没没的叫");
	}
}

5、静态代理模式

package com.huanletao.test;

public class Dog_StaticProxy implements Animal{
	private Dog dog = new Dog();
	@Override
	public void eat() {
		//代理了被代理者dog的eat方法
		dog.eat();
	}
	@Override
	public void say() {
		//没有代理被代理者dog的say方法,自己重写了
		System.out.println("狗在哈哈哈地叫");
	}
}

继承、装饰和静态代理的测试类代码如下所示:

package com.huanletao.test;

import org.junit.Test;

//Test不能作为类名,因为是关键字
public class DogTest{
	//1、测试继承——向上造型,有什么方法看父类,具体什么方法看子类
	@Test
   public void test01(){
	  Dog dog = new Dog_extends();
      dog.eat();
      dog.say();
   }
	
   //2、测试装饰——首先创建被装饰类的对象,然后把这个对象放到装饰类的有参构造里
	@Test
	public void test02(){
		Dog dog = new Dog();
		Dog_ZS zsdog = new Dog_ZS(dog);
	    zsdog.eat();
	    zsdog.say();
	}
	
	//3、测试静态代理——直接用静态代理类创建对象即可
	@Test
	public void test03(){
		Dog_StaticProxy sproxydog = new Dog_StaticProxy();
		sproxydog.eat();
		sproxydog.say();
	}
	
}

运行结果:

狗在么么么地吃
狗在喵喵喵地叫
狗在么么么地吃
狗在没没没的叫
狗在么么么地吃
狗在哈哈哈地叫

6、动态代理模式(java自带的Proxy类)

package com.huanletao.test;

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

public class Dog_Proxy  {
	public static void main(String[] args) {
		 //创建被代理类的对象
		 //注意动态代理中被代理者只能设置为final类!此时不能有private,因为二者不能共存!
		final Dog dog = new Dog();
		//调用java自带的Proxy静态类的newProxyInstance()方法生成代理者,这个代理者的类型是接口,即Animal
		Animal proxy = (Animal) Proxy.newProxyInstance(
		//第一个参数是生成代理者的加载器,和代理者的一样即可		      
				dog.getClass().getClassLoader(),
	    //第二个参数是生成代理者实现的接口们, 和代理者的一样,从而保证方法一样
				dog.getClass().getInterfaces(),
	    //第三个参数最重要,创建一个类实现InvocationHandler接口(直接new不需要implement),并实现其中的invoke方法
				       new InvocationHandler() {
						@Override
		public Object invoke(Object proxy, Method method, Object[] args)
								throws Throwable {
							//如果调用代理者的方法名是say则输出下面内容,否则输出另一种内容。
						     if("say".equals(method.getName())){
						    	 System.out.println("狗在666地叫");
						    	 return null;
						     }else{
						    	 //这里的第一个参数obj是被代理者dog
						    	 return method.invoke(dog, args);
						     }
						}
					});
		//从此只能调用动态代理者身上的方法,不能调用被代理者身上的方法
		proxy.eat();
		proxy.say();
	}
}

动态代理模式没有写测试类,直接main函数运行结果如下:

狗在么么么地吃
狗在666地叫

注:如果觉得在静态类Proxy的newProxyInstance()方法里第三个参数这样写比较难以理解,可以在外面创建一个类实现InvocationHandler接口,并实现里面的invoke方法,然后这里就可以不写main方法,而是写在上面的测试类中,然后在测试方法中调用静态类Proxy的newProxyInstance()方法,方法中第三个参数直接new写好的InvocationHandler接口的实现类即可。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值