1. 定义
为其他对象提供一种代理以控制对这个对象的访问。
代理模式是通过创建一个代理对象,用这个代理对象去代表真实的对象,客户端得到这个代理对象后,对客户端并没有什么影响,就跟得到了真实对象一样来使用。
当客户端操作这个代理对象的时候,实际上功能最终还是会由真实的对象来完成,只不过是通过代理操作的,也就是客户端操作代理,代理操作真正的对象。
2. 类图

Proxy: 代理对象,通常包含了以下功能,实现了与具体目标对象一样的借口,保存一个指向具体目标对象的引用,可以在需要的时候调用具体的目标对象,可以控制对具体目标对象的访问,并可以负责创建和删除它。
Subject: 目标对象,定义代理和具体目标对象的借口。
RealSubject: 具体目标对象,真正实现目标对象要求的功能。
3. 实例
package com.jerry.designpattern.proxy;
/**
*
* @author Jerry
* @date 2015年1月21日 上午10:39:09
*/
public interface Player {
void killMonster();
}
package com.jerry.designpattern.proxy;
/**
*
* @author Jerry
* @date 2015年1月21日 上午10:46:10
*/
public class PlayerImpl implements Player{
/**
* 经验值 experience points
*/
private int exp;
/**
* 等级
*/
private int level;
public PlayerImpl() {
level = 1;
}
@Override
public void killMonster() {
// TODO Auto-generated method stub
System.out.println("杀死一个怪物,获得50点经验");
exp += 50;
upgrade();
}
/**
* 升级
*/
private void upgrade() {
// TODO Auto-generated method stub
if (exp % 100 == 0) {
this.level++;
System.out.println("恭喜你升级了,当前等级为: " + this.level);
}
}
}
package com.jerry.designpattern.proxy;
/**
*
* @author Jerry
* @date 2015年1月21日 上午11:05:01
*/
public class GameProxy implements Player{
private Player player;
public GameProxy(Player player) {
this.player = player;
}
@Override
public void killMonster() {
// TODO Auto-generated method stub
System.out.println("游戏公式代理升级,一次升10级");
for (int i = 0; i < 20; i++) {
player.killMonster();
}
}
}
package com.jerry.designpattern.proxy;
/**
*
* @author Jerry
* @date 2015年1月21日 上午11:00:54
*/
public class Client {
public static void main(String[] args) {
/*
* 不使用游戏代理,自己手动杀怪升级
*/
Player player1 = new PlayerImpl();
player1.killMonster();
player1.killMonster();
player1.killMonster();
player1.killMonster();
/*
* 花费money找代理升级
* 一次升10级
*/
Player player2 = new PlayerImpl();
Player proxy = new GameProxy(player2);
proxy.killMonster();
proxy.killMonster();
}
}
4. 代理的分类
代理大致可以分为:
虚代理:根据需要来创建开销很大的对象,该对象只有在真正使用的时候才被创建。
远程代理:用来在不同地址空间上代表相同的一个对象,这个不同地址空间可以在本机上,也可以在其他机器上。在Java中最经典的是RMI
copy-on-write代理:在客户端操作的时候,只有对象确实改变了,才会真正的拷贝或克隆一个目标对象,算是虚代理的一个分支。
保护代理:控制原始对象的访问,如果有需要,可以给不同的用户提供不同的访问权限,以控制对原始对象的访问。
Cache代理:为那些昂贵操作的结构提供临时空间,以便多个客户端可以共享这些结果。
防火墙代理:保护对象不被恶意用户访问和操作。
同步代理:使多个用户能够同时访问目标对象而没有冲突。
智能指引:在访问对象时执行一些附加的操作。
5. 动态代理
Java对代理模式提供了内建的支持,在java.lang.reflect包下面,提供了一个Proxy和一个InvacationHandler接口,通常前面自己实现的代理模式称为静态代理,使用Java提供的功能实现的代理模式称为动态代理,
package com.jerry.designpattern.dynamicproxy;
/**
*
* @author Jerry
* @date 2015年1月21日 上午10:39:09
*/
public interface Player {
void killMonster();
}
package com.jerry.designpattern.dynamicproxy;
/**
*
* @author Jerry
* @date 2015年1月21日 上午10:46:10
*/
public class PlayerImpl implements Player{
/**
* 经验值 experience points
*/
private int exp;
/**
* 等级
*/
private int level;
public PlayerImpl() {
level = 1;
}
@Override
public void killMonster() {
// TODO Auto-generated method stub
System.out.println("杀死一个怪物,获得50点经验");
exp += 50;
upgrade();
}
/**
* 升级
*/
private void upgrade() {
// TODO Auto-generated method stub
if (exp % 100 == 0) {
this.level++;
System.out.println("恭喜你升级了,当前等级为: " + this.level);
}
}
}
package com.jerry.designpattern.dynamicproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
*
* @author Jerry
* @date 2015年1月21日 上午11:13:19
*/
public class GameProxy implements InvocationHandler{
public Player player;
public GameProxy(Player player) {
this.player = player;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
System.out.println("使用游戏代理升级,一次升10级");
for (int i = 0; i < 20; i++) {
method.invoke(player, args);
}
return null;
}
public Player getInstance() {
return (Player)Proxy.newProxyInstance(player.getClass().getClassLoader(),
player.getClass().getInterfaces(),
this);
}
}
package com.jerry.designpattern.dynamicproxy;
/**
*
* @author Jerry
* @date 2015年1月21日 上午11:20:16
*/
public class Client {
public static void main(String[] args) {
Player player = new PlayerImpl();
GameProxy gameProxy = new GameProxy(player);
Player playerProxy = gameProxy.getInstance();
playerProxy.killMonster();
}
}
来源:https://www.cnblogs.com/jerry19890622/p/4310007.html