AOP实现机制 - 代理模式
代理模式
(1)真是角色更加纯粹!不需要关心一些公共业务。
(2)公共业务也就交给了代理角色。
(3)公共业务大声扩展的时候,方便集中管理。
下边以房东、中介、客户为例,记录下静态代理模式
下边代码思路很清晰: 房东只想出租房子,而中介会帮助(代理出租房子的权限)房主出租房子,客户要租房子住。
接口
接口只是一个房子要出租的这么一个方法
package com.lxc.domain;
public interface Rent {
public void rentOutHouse();
}
房东
只有房子的主人才可以出租房子,所以他要实现上边的接口;(这块补充下:但是由于房东资源有限,也找不到要租房子的人,所以最后他决定把房子交给中介,让中介帮忙出租房屋)
package com.lxc.domain;
public class Host implements Rent{
@Override
public void rentOutHouse() {
System.out.println("房东出租房子");
}
}
中介
中介这一层是帮助房子主人出租房子的,中介有出租房子的权限,相当于把出租房子的权限代理过来了,而且,中介还有一些自己的业务,比如:签合同、收中介费 ···
package com.lxc.domain;
/**
* 中介 - 把出租房子权限代理过来了
*/
public class Proxy {
private Host host; // 房子的主人,只有中介才能接触房主,客户不会直接接触
public Proxy() {
Host host = new Host();
this.setHost(host);
}
public Host getHost() {
return host;
}
public void setHost(Host host) {
this.host = host;
}
public void rentHost() {
// 中间出租房子,实际上他是去找房主人rentOutHouse的这个方法
this.host.rentOutHouse();
// 下边中介还有的业务
this.collectAgentFee();
this.signHT();
}
private void collectAgentFee() { // 收中介费
System.out.println("收中介费");
}
private void signHT() { // 签合同
System.out.println("签合同");
}
}
客户
要找租房,房子住,因为能力有限,所以,他会去找中介
package com.lxc.domain;
/**
* 客户 - 需要租房子住
*/
public class Agent {
public static void main(String[] args) {
// 客户找到中介Proxy,要跟中介说需求,
Proxy proxy = new Proxy();
// 客户的需求 - 租房子
lookHouse(proxy);
}
// 需求要租房子
private static void lookHouse(Proxy proxy) {
// 中介会调用出租房子的方法
proxy.rentHost();
}
}
输出结果:
可能有人会问,理解上边逻辑有个P用???
刚开始我也觉得没P用,但又想了想,既然有代理模式,那么必然有它的用处,下边模仿简单的真实开发场景:
一个UserService接口,假设有50个接口(下边为了方便只写了4个接口),增删改查还有一些根据id、下拉、模糊查询等等。
package com.lxc.service;
public interface UserService {
public void query();
public void add();
public void update();
public void delete();
// 此处省略N个接口 ···
}
实现UserService接口
package com.lxc.service;
public class UserServiceImp implements UserService{
@Override
public void query() {
System.out.println("查询");
}
@Override
public void add() {
System.out.println("增加");
}
@Override
public void update() {
System.out.println("编辑");
}
@Override
public void delete() {
System.out.println("删除");
}
}
我们来测试调用,查询方法
package com.lxc.service;
public class Test {
public static void main(String[] args) {
UserServiceImp userServiceImp = new UserServiceImp();
userServiceImp.add();
}
}
输出如下:
很成功哈,嘴角疯狂上移。第二天主管让把所有的接口加上日志,你会怎么做?在原有接口代码中添加日志功能?显然这种做法不太友好,万一一个月之后需求又改了,让把日志取消掉呢,又加了一些新功能?你会直接崩溃掉!
此时,使用代理模式会帮助你减少很多无用的操作,而且,这种方式,不会在原有业务代码中去做修改,来看下:
加一层代理,UserServiceProxy类实现代理功能,这样外界直接调用代理的方法即可,由代理的方法去调用真实的增删改查的方法。
package com.lxc.service;
public class UserServiceProxy {
private UserServiceImp userServiceImp;
// 构造器,外界new UserServiceProxy时,这里我们要拿到真实的UserServiceImp,以便代理增删改查
public UserServiceProxy() {
this.setUserServiceImp(new UserServiceImp());
}
public void setUserServiceImp(UserServiceImp userServiceImp) {
this.userServiceImp = userServiceImp;
}
// 代理增删改查的接口
public void query() {
log("query");
userServiceImp.query();
}
public void add() {
log("add");
userServiceImp.add();
}
public void update() {
log("update");
userServiceImp.update();
}
public void delete() {
log("delete");
userServiceImp.delete();
}
// 日志功能
private void log(String info) {
System.out.println("调用了" + info + "方法");
}
}
外界调用代理方法:
package com.lxc.service;
public class Test {
public static void main(String[] args) {
UserServiceProxy userServiceProxy = new UserServiceProxy();
userServiceProxy.add();
}
}
输出如下:
这种代理模式,跟Python中的装饰器有点像,不去改变原有代码的基础上,添加功能。反复琢磨下,租房子和上边模拟的真实开发场景例子,感觉代理模式确实非常棒的。