定义
为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
UML
抽象角色:通过接口或抽象类声明真实角色实现的业务方法。
代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。(最简单的比如打印日志)
真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。
实例
代理商,本身不生成产品,但是从厂家拿产品卖个用户。起到媒介作用。
java的代理模式
简单demo:
/**
* 抽象主题,定义主要功能
*/
publicinterface Subject {
publicvoid operate();
}
/**
* 具体主题
*/
publicclass RealSubject implements Subject{
@Override
publicvoid operate() {
System.out.println("realsubject operatestarted......");
}
}
/**
* 代理类
*/
publicclass Proxy implements Subject{
private Subject subject;
public Proxy(Subject subject) {
this.subject = subject;
}
@Override
publicvoid operate() {
System.out.println("before operate......");
subject.operate();
System.out.println("after operate......");
}
}
public class Client {
publicstaticvoid main(String[] args) {
Subject subject = new RealSubject();
Proxy proxy = new Proxy(subject);
proxy.operate();
}
}
动态代理
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.lang.reflect.Method;
//抽象角色:java动态代理的实现目前只支持接口,不支持抽象类
interface BusinessFoo
{
void foo();
}
interface BusinessBar
{
String bar(String message);
}
//真实角色:真正实现业务逻辑方法
class BusinessFooImpl implements BusinessFoo
{
public void foo()
{
System.out.println("BusinessFooImpl.foo()");
}
}
class BusinessBarImpl implements BusinessBar
{
public String bar(String message)
{
System.out.println("BusinessBarImpl.bar()");
return message;
}
}
//动态角色:动态生成代理类
class BusinessImplProxy implements InvocationHandler
{
private Object obj;
BusinessImplProxy() {
}
BusinessImplProxy(Object obj) {
this.obj = obj;
}
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable
{
Object result = null;
doBefore();
result = method.invoke(obj,args);
doAfter();
return result;
}
public void doBefore(){
System.out.println("do something before Business Logic");
}
public void doAfter(){
System.out.println("do something after Business Logic");
}
public static Object factory(Object obj)
{
Class cls = obj.getClass();
return Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),new BusinessImplProxy(obj));
}
}
//测试类
public class DynamicProxy
{
public static void main(String[] args) throws Throwable
{
BusinessFooImpl bfoo = new BusinessFooImpl();
BusinessFoo bf = (BusinessFoo)BusinessImplProxy.factory(bfoo);
bf.foo();
System.out.println();
BusinessBarImpl bbar = new BusinessBarImpl();
BusinessBar bb = (BusinessBar)BusinessImplProxy.factory(bbar);
String message = bb.bar("Hello,World");
System.out.println(message);
}
}
优点
(1).职责清晰真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理完成一件完成事务,附带的结果就是编程简洁清晰。
(2).代理对象可以在客户端和目标对象之间起到中介的作用,这样起到了的作用和保护了目标对象的作用。
(3).高扩展性
比较
代理模式与外观模式的区别:
1、外观模式也是屏蔽复杂性的,但是外观模式不会实现客户端调用的目标类型接口。
2、一般客户端调用外观模式的方法都是直接调用。
3、代理模式中对客户端目标对象类型抽象接口具体化了。
4、外观模式是代理模式中一种特殊的子级模式(广泛的,非约束性)。
代理模式与适配器模式区别
适配器为它所适配的对象提供了一个不同的接口。相反,代理提供了与它的实体相同的接口。然而,用于访问保护的代理可能会拒绝执行实体会执行的操作,
因此,它的接口实际上可能只是实体接口的一个子集。
代理模式与装饰器模式区别
尽管装饰器的实现部分与代理相似,但装饰器的目的不一样。装饰器为对象添加一个或多个功能,而代理则控制对对象的访问。