设计模式(六)—代理模式
最后更新于:2022-04-01 16:26:04
**英文名称:Proxy Pattern**
**定义**:为其他对象提供一种代理以控制对这个对象的访问。
**我的理解**:代理模式相当于现实生活中的明星经纪人,提供了一个很好的访问控制。
**代理模式的分类:**
静态代理模式
--|普通代理模式
--|强制代理模式
动态代理模式
## 代理模式的一般模式:![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_57553409246a2.jpg)
###Subject抽象主题角色
--|抽象主题类可以是抽象类也可以是接口,是一个最普通的业务型定义,无特殊要求。
### RealSubject具体主题角色
--|也被叫做委托角色、被代理角色。是业务逻辑的具体执行者
### Proxy代理主题角色
--|也叫作代理类、委托类。负责对真实角色的应用,把所有抽象主题类定义的方法限制委托给真实角色实现, 并且在真实主题角色处理完毕后做预处理和善后处理工作。
~~~
public class ProxyTest {
public static void main(String[] args) {
//实例化一个真实的被委托类。
System.out.println("---------实例化一个真实的被委托类--------------");
Proxy realSubject = new Proxy(new RealSubject());
realSubject.request();
}
}
interface Subject{
//定义一个方法,让子类去实现
public void request();
}
class RealSubject implements Subject{
//被委托角色,执行具体是方法实现
@Override
public void request() {
System.out.println("我是RealSubject,我在执行方法....");
}
}
class Proxy implements Subject{
//代理类,负责真实角色的应用。
private Subject subject = null;
//设置想要的被代理者
public Proxy(Subject subject){
this.subject = subject;
}
@Override
public void request() {
before();
this.subject.request();
after();
}
private void before(){
System.out.println("代理类,在做事前处理...");
}
private void after(){
System.out.println("代理类,在做善后处理...");
}
}
~~~
##普通代理模式:
--|要求客户端只能访问代理角色,而不能访问真实角色。
一个例子:
一款非常著名的游戏,游戏玩家需要整天的登录、打怪、升级。但是游戏玩家没有时间, 所以他需要找一个代理来替他完成这个重复的过程,并使得游戏技能提升。
--|IGamePlayer游戏玩家接口,定义login(String name,String password)
killBoss()、upGrade()
--|GamePlayer 游戏玩家,真正的被委托类,实现这些游戏方法。
--|GameProxy 游戏代理,通过代理设置,去委托真实类实现需要的方法。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_575534093bb69.jpg)
~~~
public class CommonProxy {
public static void main(String[] args) {
String name = "xy";
GameProxy proxy = new GameProxy(name);
proxy.login(name, "Ilovelzl");
proxy.killBoss();
proxy.upGrade();
System.out.println("-----代理时间到--------");
}
}
interface IGamePlayer{
void login(String name,String password);
void killBoss();
void upGrade();
}
class GameProxy implements IGamePlayer{
private GamePlayer gamePlayer = null;
//通过构造函数来传递要对谁进行游戏代理
public GameProxy(String name) {
try {
this.gamePlayer = new GamePlayer(this, name);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void login(String name, String password) {
this.gamePlayer.login(name, password);
}
@Override
public void killBoss() {
this.gamePlayer.killBoss();
}
@Override
public void upGrade() {
this.gamePlayer.upGrade();
}
}
class GamePlayer implements IGamePlayer{
private String name="";
//设置一个提供代理类的构造函数,限制用户必须通过代理类来实例化对象。
public GamePlayer(IGamePlayer iGamePlayer,String name)throws Exception {
if(iGamePlayer == null){
throw new Exception("不能创建角色");
}else{
this.name = name;
}
}
@Override
public void login(String name, String password) {
System.out.println("用户:"+this.name+"登录成功!");
}
@Override
public void killBoss() {
System.out.println(this.name+"在打怪!");
}
@Override
public void upGrade() {
System.out.println(this.name+"又升了一级...");
}
}
~~~
### 强制代理
---|必须通过真实角色找到代理角色,否则不能访问。
依旧是打怪的例子实现;
~~~
public class CommonProxy {
public static void main(String[] args) {
//首先创建一个游戏玩家
System.out.println("------只创建一个玩家,不设置代理的效果---------");
GamePlayer xy = new GamePlayer("xy");
xy.login("xy", "pass");
xy.killBoss();
xy.upGrade();
System.out.println("------创建一个玩家,并设置代理的效果---------");
GameProxy proxy = (GameProxy) xy.getProxy();
proxy.login("xy", "pass");
proxy.killBoss();
proxy.upGrade();
}
}
interface IGamePlayer{
void login(String name,String password);
void killBoss();
void upGrade();
IGamePlayer getProxy();
}
class GameProxy implements IGamePlayer{
private IGamePlayer gamePlayer = null;
//通过构造函数来传递要对谁进行游戏代理
public GameProxy(IGamePlayer gamePlayer) {
this.gamePlayer = gamePlayer;
}
@Override
public void login(String name, String password) {
this.gamePlayer.login(name, password);
}
@Override
public void killBoss() {
this.gamePlayer.killBoss();
}
@Override
public void upGrade() {
this.gamePlayer.upGrade();
}
//设置代理,代理没有具体的实例,因此暂时返回自己。
@Override
public IGamePlayer getProxy() {
// TODO Auto-generated method stub
return this;
}
}
class GamePlayer implements IGamePlayer{
private String name="";
private IGamePlayer proxy = null;
//设置一个提供代理类的构造函数,限制用户必须通过代理类来实例化对象。
public GamePlayer(String name) {
this.name = name;
}
//设置代理
@Override
public IGamePlayer getProxy() {
this.proxy = new GameProxy(this);
return this.proxy;
}
@Override
public void login(String name, String password) {
if(this.isProxy()){
System.out.println("用户:"+this.name+"登录成功!");
}
else{
System.out.println("请使用指定的代理访问...");
}
}
@Override
public void killBoss() {
if(this.isProxy()){
System.out.println(this.name+"在打怪!");
}
else{
System.out.println("请使用指定的代理访问...");
}
}
@Override
public void upGrade() {
if(this.isProxy()){
System.out.println(this.name+"又升了一级!");
}
else{
System.out.println("请使用指定的代理访问...");
}
}
private boolean isProxy(){
if( proxy == null){
return false;
}
return true;
}
}
~~~
### 动态代理
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_57553409549fa.jpg)
~~~
public class DynamicProxy {
public static void main(String[] args) {
//定义一个游戏玩家
MyIGamePlayer player = new MyGamePlayer("lzl");
//定义一个handler
InvocationHandler handler = new GamePlayIH(player);
//开始游戏,获得类的classLoader
ClassLoader cl = player.getClass().getClassLoader();
//动态产生一个代理者
MyIGamePlayer proxy = (MyIGamePlayer)Proxy.newProxyInstance(cl,new Class[]{MyIGamePlayer.class},
handler);
proxy.login("lzl", "123");
proxy.killBoss();
proxy.upGrade();
}
}
interface MyIGamePlayer{
void login(String name,String password);
void killBoss();
void upGrade();
}
class GamePlayIH implements InvocationHandler{
//设置动态代理,必须继承InvocationHandler接口。并实现invoker方法
//被代理者
Class cls = null;
Object obj = null;
public GamePlayIH(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("killBoss")){
System.out.println("有人用我的账号登录...");
}
return result;
}
}
class MyGamePlayer implements MyIGamePlayer{
private String name="";
//设置一个提供代理类的构造函数,限制用户必须通过代理类来实例化对象。
public MyGamePlayer(String name){
this.name = name;
}
@Override
public void login(String name, String password) {
System.out.println("用户:"+this.name+"登录成功!");
}
@Override
public void killBoss() {
System.out.println(this.name+"在打怪!");
}
@Override
public void upGrade() {
System.out.println(this.name+"又升了一级...");
}
}
~~~
**动态代理的一般模式**:
AOP:面向横切面编程。
动态代理实现代理的职责,业务逻辑ISubject实现相关的逻辑给你。
两者时间没有必然的相互耦合关系。
通知Advice从另一个切面切入,最终在高层模块也是ProxyT进行耦合,完成逻辑的封装任务。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_57553409728ad.jpg)
~~~
public class ProxyT {
public static void main(String[] args) {
/*//定义一个主题
ISubject sub = new MySubject();
//定义主题代理
ISubject proxy = SubjectDynamicProxy.newProxyInstance(sub);
proxy.doSomething();*/
}
}
interface ISubject{
void doSomething();
}
class MySubject implements ISubject{
@Override
public void doSomething() {
System.out.println("子类具体实现方法...");
}
}
interface Advice{
void someAdvice();
}
class MyAdvice implements Advice{
//该类用于说明,在
@Override
public void someAdvice() {
System.out.println("一些前言方法...");
}
}
/**
* 动态代理的Handler类
* @author admin
*
*/
class MyInvocation implements InvocationHandler{
Object obj = null;
public MyInvocation(Object obj) {
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
return method.invoke(obj, args);
}
}
class SubjectDynamicProxy{
public static <T> T newProxyInstance(ISubject subject){
//获取类加载器
ClassLoader loader = subject.getClass().getClassLoader();
//获得接口数组
Class<?>[] interfaces = subject.getClass().getInterfaces();
//获得handler
InvocationHandler handler = new MyInvocation(subject);
return (T)Proxy.newProxyInstance(loader, interfaces, handler);
}
}
~~~
也可以将上面的改为SubjectDynamicProxy改为DynamicProxys。
~~~
class DynamicProxys{
@SuppressWarnings("unchecked")
public static <T> T newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,InvocationHandler handler ){
if(true){
//执行一个前置通知..
new MyAdvice().someAdvice();
}
return (T)Proxy.newProxyInstance(loader, interfaces, handler);
}
~~~