Java学习-设计模式-代理模式
概述
在代理模式中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。
在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。
优点: 1、职责清晰。 2、高扩展性。 3、智能化。
缺点: 1、由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。 2、实现代理模式需要额外的工作,有些代理模式的实现非常复杂。
理解:
之前说过这个和装饰器模式有点类似,之前装饰器模式举的是进水果的例子,这里照着之前的写,然后改为代理模式感觉在这有点不好写了,还是改为之前早就想好的例子(定外卖)。
1. 先定义一个定外卖的接口A,包含一定定外卖的方法
2. 创建一个实现类A1实现接口A,包含一个菜名的属性,构造方法中初始化这个菜名,然后重写定外卖方法,定这个菜名的外卖
3. 创建一个代理类(类似外卖派送员),包含一个类型为接口A的属性。在构造方法中使用实现类初始化属性,然后创建一个方法,通过枚举,判定外卖员忙不忙,忙则不派送,不忙则派送(测试时变成了下单成不成功了)。
4. 测试
示例:
- 静态代理
package Practices.Mode.Proxy_Pattern;
// 1. 定义外卖接口(外卖这个单词不知道怎么翻译,谷歌竟然给我翻译为take away)
public interface foods {
public void shopping_foods();
}
package Practices.Mode.Proxy_Pattern;
// 2. 创建一个外卖的实现类,定具体的外卖
public class food1 implements foods {
private String food_name;
public food1(String food_name) {
this.food_name = food_name;
}
public void shopping_foods() {
System.out.println("定一份"+food_name+"成功");
}
}
package Practices.Mode.Proxy_Pattern;
import java.util.Random;
// 3. 创建一个代理类,根据外卖派送员的状态来决定送不送这份外卖
public class Send_Food_people {
private foods food;
public Send_Food_people() {
this.food = new food1("鱼香茄子");
}
public void getfood(){
Status enums[] = Status.values();
Random random = new Random();
Status ed = enums[random.nextInt(enums.length)];
if(ed==Status.busy){
System.out.println("业务繁忙,暂不接单");
}else{
food.shopping_foods();
}
}
}
// 使用枚举定义外卖派送员的状态
enum Status{
busy,
idle;
}
package Practices.Mode.Proxy_Pattern;
// 4. 测试
public class Test_main {
public static void main(String[] args) {
Send_Food_people send_food_people = new Send_Food_people();
send_food_people.getfood();
}
}
-
动态代理(第一种)
在
java
的java.lang.reflect
包下提供了一个Proxy
类和一个InvocationHandler
接口,通过这个类和这个接口可以生成JDK
动态代理类和动态代理对象。
package Practices.Mode.Proxy_Pattern;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 动态代理
public class Test_main2 {
public static void main(String[] args) {
final foods food = new food1("辣椒炒肉");
foods proxy = (foods) Proxy.newProxyInstance(
food.getClass().getClassLoader(), // 参数一:指定当前目标对象使用类加载器,写法固定
food.getClass().getInterfaces(), // 参数二:目标对象实现的接口的类型,写法固定
new InvocationHandler() { // 参数三:事件处理接口,需传入一个实现类,一般直接使用匿名内部类
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object returnValue = method.invoke(food, args);// 这里是执行目标对应的方法
return returnValue;
}
}
);
proxy.shopping_foods();
}
}
-
还有一种使用 Cglib 类实现动态代理
前提条件:
需要引入cglib的jar文件,由于
Spring
的核心包中已经包括了Cglib功能,所以也可以直接引入spring-core-3.2.5.jar目标类不能为final
目标对象的方法如果为final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法.
**这个不想整了,之后又好的例子再来补齐吧。 **