Java 代理模式怎么写

在日常写代码的过程中,你有没有遇到过这种情况:想给一个已经写好的功能“加个小操作”,比如在咖啡店买咖啡时,结账前要先报会员号积分,但又不想把“报会员号”这件事直接塞进做咖啡的代码里?这时候,“代理”这个帮手就派上用场了,而Java里的代理模式,其实就是这个思路的代码实现。

先搞懂:代理模式到底是啥?

简单说,代理就是“帮别人做事的中间人”。你想做的事(比如买咖啡),是核心任务;但核心任务前后,可能需要加一些辅助操作(比如报会员号积分、检查支付余额),这些辅助操作如果直接写在核心任务的代码里,会让代码变得乱、难维护——比如哪天不需要积分了,还要去核心代码里删东西,容易改错。

Java 代理模式怎么写

代理模式的核心,就是把“核心任务”和“辅助操作”分开,让中间人(代理)来负责做辅助操作,只在需要的时候让代理去对接核心任务,核心任务本身不用改。还是用咖啡店举例:你是“买咖啡”的人(核心任务),咖啡店的服务员是“代理”,你只要说“帮我买一杯拿铁”,服务员就会先跟你确认会员号(辅助操作),再去后厨拿咖啡(核心任务),最后帮你积分(另一个辅助操作),你不用关心服务员怎么跟后厨对接,也不用把积分的事挂在嘴边。

用Java写一个最简单的代理:静态代理

先从好理解的“静态代理”开始,这种代理是写代码时就定死的,不会变。

第一步,先定义一个“统一的做事规范”(接口),不管是核心任务(你买咖啡)还是代理(服务员),都要遵守这个规范:

`java

// 定义买咖啡的规范

interface CoffeeShop {

void buyCoffee(String type);

}

`

第二步,写核心任务的实现类,也就是“后厨”,它只负责真正做咖啡,不管别的:

`java

// 核心任务:后厨做咖啡

class BackendKitchen implements CoffeeShop {

@Override

public void buyCoffee(String type) {

System.out.println("后厨做了一杯" + type);

}

}

`

第三步,写代理类,也就是服务员,它要遵守买咖啡的规范,同时负责做辅助操作:

`java

// 代理类:服务员

class Waiter implements CoffeeShop {

// 持有核心任务的引用,相当于服务员认识后厨

private CoffeeShop kitchen = new BackendKitchen();

@Override

public void buyCoffee(String type) {

// 辅助操作1:先确认会员号(这里简化成模拟)

System.out.println("服务员:请问您的会员号是多少?");

// 辅助操作2:调用核心任务,让后厨做咖啡

kitchen.buyCoffee(type);

// 辅助操作3:做完咖啡帮你积分

System.out.println("服务员:已为您本次消费积分");

}

}

`

最后测试一下,你只需要跟服务员说买咖啡,就能自动完成所有步骤:

`java

public class Main {

public static void main(String[] args) {

CoffeeShop waiter = new Waiter();

waiter.buyCoffee("拿铁");

}

}

`

运行后会输出:服务员:请问您的会员号是多少?后厨做了一杯拿铁服务员:已为您本次消费积分。你看,核心任务只写了一次,辅助操作全在代理里,改辅助操作也不用动后厨的代码,是不是很灵活?

更灵活的动态代理:不用提前写死代理

刚才的静态代理,每个核心任务都要写一个对应的代理类,如果有很多不同的核心任务,代理类会越来越多。这时候用动态代理就方便了——运行时才生成代理,不用提前写死。

Java自带的动态代理需要用到InvocationHandler,相当于一个“通用的代理调度员”,它会帮你处理所有的辅助操作,再对接核心任务。比如把刚才的买咖啡,改成用动态代理实现,只需要写一个调度员:

`java

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

import java.lang.reflect.Proxy;

// 动态代理的调度员,负责处理辅助操作

class CoffeeHandler implements InvocationHandler {

// 核心任务的引用

private Object target;

public CoffeeHandler(Object target) {

this.target = target;

}

@Override

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

// 辅助操作:调用核心任务前先确认会员

System.out.println("服务员:请问您的会员号是多少?");

// 调用核心任务的真正方法

Object result = method.invoke(target, args);

// 辅助操作:调用完核心任务后积分

System.out.println("服务员:已为您本次消费积分");

return result;

}

}

`

测试的时候,不用再单独写服务员的类,直接生成动态代理:

`java

public class DynamicProxyMain {

public static void main(String[] args) {

// 核心任务对象

CoffeeShop kitchen = new BackendKitchen();

// 创建调度员

InvocationHandler handler = new CoffeeHandler(kitchen);

// 生成动态代理对象

CoffeeShop proxy = (CoffeeShop) Proxy.newProxyInstance(

kitchen.getClass().getClassLoader(),

kitchen.getClass().getInterfaces(),

handler

);

// 调用代理的方法,自动走辅助操作

proxy.buyCoffee("美式");

}

}

`

运行结果和静态代理一样,但好处是:如果以后要加“买奶茶”的核心任务,不用再写新的代理类,只要把核心任务的对象传给调度员就行,代码复用性更高。

什么时候用代理模式?

如果你的代码需要“在核心逻辑前后加统一的辅助操作”,比如日志记录、权限校验、事务管理,又不想把这些辅助逻辑和核心逻辑混在一起,就可以用代理模式——它就像一个“代码中间人”,帮你把复杂的辅助操作单独管理,让核心代码更干净,也更容易维护。

上一篇 PHP 如何做代码检查