该篇是主要说明代理模式
定义
为其他对象提供一种代理以控制对这个对象的访问。
代理模式也叫作委托模式。
角色
1.Subject抽象主题角色
可以是抽象类也可以是接口,是一个最普通的业务类型定义,无特殊要求。
代码如下:
public interface Subject {
// 定义一个方法
void request();
}
2.RealSubject具体主题角色
也叫做被委托角色、被代理角色。是业务逻辑的具体执行者。
代码如下:
public class RealSubject implements Subject {
// 实现方法
@Override
public void request() {
System.out.println("调用我");
}
}
3.Proxy代理主题角色
也叫做委托类、代理类。负责对真实角色的应用,把所有抽象主题类定义的方法限制委托给真实主体角色实现,并且在真实主体角色处理完毕前后做预处理和善后处理工作。
代理模式的核心就在代理类上。
代码如下:
public class Proxy implements Subject {
private Subject subject = null;
// 默认被代理者
public Proxy() {
this.subject = new RealSubject();
}
public Proxy(Subject subject) {
this.subject = subject;
}
@Override
public void request() {
this.before();
this.subject.request();
this.after();
}
// 预处理
private void before(){
System.out.println("before");
}
// 善后处理
private void after(){
System.out.println("after");
}
}
代码执行及结果
执行代码
public static void main(String[] args) {
Proxy proxy = new Proxy();
proxy.request();
RealSubject realSubject = new RealSubject();
Proxy proxy1 = new Proxy(realSubject);
proxy1.request();
}
结果:
before
调用我
after
before
调用我
after
代理模式优缺点
优点:
- 职责清晰。真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事物。
- 高扩展性。具体主题角色是随时都会发生变化,只要实现它接口即可。我的代理类完全可以不做任何修改即可以使用。
- 智能化。
缺点:
- 由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。
- 实现代理模式需要额外的工作,有些代理模式的实现非常复杂。
扩展
1.普通代理
普通代理需要用户自己设置代理服务器的IP地址,用户必须知道代理的存在,然后才能访问。强制代理则是调用者直接调用真实角色,而不用关心代理是否存在,其代理的产生是由真实角色决定的。
普通代理客户端只能访问代理角色,不能访问真实角色。
修改:
代理类不需要传递进入被代理类的构造函数,同时,被代理类构造参数传入实现类。
接口:
public interface CommonSubject {
void doSomething();
}
实现类:
public class CommonRealSubject implements CommonSubject {
public CommonRealSubject(CommonSubject subject) {
if (null==subject)
throw new NullPointerException("subject is null");
}
@Override
public void doSomething() {
System.out.println("common real subject");
}
}
代理类
public class CommonProxy implements CommonSubject {
private CommonRealSubject realSubject = null;
public CommonProxy() {
realSubject = new CommonRealSubject(this);
}
@Override
public void doSomething() {
this.realSubject.doSomething();
}
}
2.强制代理
强制代理必须通过真实角色查找到代理角色,否则不能访问。
接口:
public interface Player {
void doSomething();
// 获取类的指定代理,除了代理外,谁都不能访问。
Player getProxy();
}
代理类:
public class PlayerProxy implements Player {
private Player player = null;
public PlayerProxy(Player player) {
this.player = player;
}
@Override
public void doSomething() {
this.player.doSomething();
}
@Override
public Player getProxy() {
return this;
}
}
被代理类:
public class RealPlayer implements Player{
private Player player = null;
@Override
public void doSomething() {
if (this.isProxy()){
System.out.println("real player");
}else {
System.out.println("请使用代理");
}
}
@Override
public Player getProxy() {
this.player = new PlayerProxy(this);
return this.player;
}
private boolean isProxy(){
if (null==player){
return false;
}
return true;
}
}
3.动态代理
动态代理是在实现阶段不用关心代理谁,而在运行阶段才指定代理哪一个对象。相对来说,自己写代理类的方式就是静态代理。
实现InvocationHandler
接口。
代码:
public class PlayerIH implements InvocationHandler {
// 被代理者
Class cls = null;
// 被代理者的实例
Object obj = null;
// 我要代理谁
public PlayerIH(Object obj) {
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(this.obj,args);
if (method.getName().equalsIgnoreCase("login")){
System.out.println("登录");
}
return result;
}
}