Java设计模式—代理模式

(尊重劳动成果,转载请注明出处:https://blog.csdn.net/qq_25827845/article/details/52452953冷血之心的博客)

目录

代理模式:

个人理解:

通用类图如下:

角色定义:

通用源代码:

代理模式的优点:

案例分析:

类图如下:

通用源代码如下:

 代理模式的扩展:

普通代理:

强制代理:

 动态代理:

动态代理Demo如下:


代理模式:

(Proxy Pattern)也叫做委托模式,是一个使用率非常高的模式。

定义:为其他对象提供一种代理以控制对这个对象的访问。

个人理解:

       代理模式将原类进行封装,客户端不能直接找到原类,必须通过代理角色。即代理是原类的一个替身,客户端要找原类,统统找代理就可以搞定。明星和经纪人就是一种代理模式。

通用类图如下:

角色定义:

● Subject 抽象主题角色
     抽象主题类可以是抽象类也可以是接口,是一个最普通的业务类型定义,无特殊要求。
● RealSubject 具体主题角色

    也叫做被委托角色、被代理角色。它才是冤大头,是业务逻辑的具体执行者。
● Proxy代理主题角色
    也叫做委托类、代理类。它负责对真实角色的应用,把所有抽象主题类定义的方法限制委托给真实主题角色实现,并且在真实主题角色处理完毕前后做预处理和善后处理工作。

通用源代码:

//抽象主题类
public interface Subject {
     //定义一个方法
     public void request();
}

在接口中我们定义了一个方法request来作为方法的代表,RealSubject对它进行实现。

//真实主题类
public class RealSubject implements Subject {
     //实现方法
     public void request() {
             //业务逻辑处理
     }
}

Real Subject是一个正常的业务实现类,代理模式的核心就在代理类上。

代理类如下:

public class Proxy implements Subject {
     //要代理哪个实现类
     private Subject subject = null;    
     //默认被代理者
     public Proxy(){
             this.subject = new Proxy();
     }
     //通过构造函数传递代理者
     public Proxy(Object...objects )    {  
   }
     //实现接口中定义的方法
     public void request() {
             this.before();
             this.subject.request();
             this.after();
     }
     //预处理
     private void before(){
             //do something
     }
     //善后处理
     private void after(){
             //do something
     }
}


代理模式的优点:

  • 职责清晰
  • 高扩展性
  • 智能化

 

案例分析:

追星族想要明星签名,必须找其经纪人搞定。

类图如下:

通用源代码如下:

//明星接口
public interface IStar {
     //明星都会签名
     public void sign();
}
//明星只有一个行为:签字。我们来看明星的实现,如代码清单3

//明星
public class Singer implements IStar {
     public void sign() {
             System.out.println("明星签字:我是XXX大明星");
     }
}


//经纪人与明星应该有相同的行为,比如说签名,虽然经纪人不签名,但是他把你要签名的笔记本、衣服、CD等传递过去让真正的明星签字,

//经纪人
public class Agent implements IStar {
     //定义是谁的经纪人
     private IStar star;
     //构造函数传递明星
     public Agent(IStar _star){
             this.star = _star;
     }
     //经纪人是不会签字的,签字了歌迷也不认
     public void sign() {
             star.sign();
     }
}
//追星族
public class Idolater {
     public static void main(String[] args) {
             //崇拜的明星是谁
             IStar star = new Singer();
             //找到明星的经纪人
             IStar agent = new Agent(star);
             System.out.println("追星族:我是你的崇拜者,请签名!");
             //签字
             agent.sign();
     }
}


很简单,找到明星的代理,然后明星就签字了。运行结果如下所示:

追星族:我是你的崇拜者,请签名!
明星签字:我是XXX大明星


看看我们的程序逻辑,我们是找明星的经纪人签字,真实签字的是明星,经纪人只是把这个请求传递给明星处理而已,这是普通的代理模式的典型应用。

 

 代理模式的扩展:

  •  普通代理
  • 强制代理
  • 动态代理

 

普通代理:

要求客户端只能访问代理角色,而不能访问真实角色。

          在该模式下,调用者只知道代理而不知道真是的角色是谁,屏蔽了真是角色的变更对高层模块的影响,真实的主

题角色想怎么修改都可以。在实际项目中,一般通过约定来禁止new一个真实的角色。

强制代理:

客户端必须通过真实角色查找到代理角色,否则你不能访问。

       就好比是你和一个明星比较熟,相互认识,有件事情你需要向她确认一下,于是你就直接拨通了明星的电话:
                  “喂,沙比呀,我要见一下×××导演,你帮下忙了!”
                 “不行呀衰哥,我这几天很忙呀,你找我的经纪人吧……”

       郁闷了吧,你是想直接绕过她的代理,谁知道返回的还是她的代理,这就是强制代理,你可以不用知道代理存在,但是你的所作所为还是需要代理为你提供。

 动态代理:

     在实现阶段不用关心代理谁,而在运行阶段才指定代理哪一个对象。相对来说,自己写代理类的方式就是静态代理。

首先我们需要学习JDK提供的动态代理接口InvocationHandler,该接口对被代理类的方法进行代理。

JDK如图所示:

其次还有一个类叫Proxy,来看JDK描述,我们主要使用了newProxyInstance( )的静态方法。

 

动态代理Demo如下:

package com.package1;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class DynamicProxy {
	
	public static void main(String[] args){
		//定义一个people作为被代理的实例
		IPeople ple=new People();
		//定义一个handler
		InvocationHandler handle=new MyHandle(ple);
		
		//获得类加载器
		ClassLoader cl=ple.getClass().getClassLoader();
		
		//动态产生一个代理,下边两种方法均可
//		IPeople p=(IPeople) Proxy.newProxyInstance(cl, new Class[]{IPeople.class}, handle);
		IPeople p=(IPeople) Proxy.newProxyInstance(cl, ple.getClass().getInterfaces(), handle);
		
		//执行被代理者的方法。
		p.func();
	}
	
	
	
}

class MyHandle implements InvocationHandler{
	

	//被代理的实例
	Object obj=null;
	
	//我要代理谁
	public MyHandle(Object obj){
		this.obj=obj;
		
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		Object result=method.invoke(this.obj, args);
		return result;
	}
	
}

interface IPeople{
	
	public void fun();
	
	public void func();
}

//实际被代理的类
class People implements IPeople{

	@Override
	public void fun() {
		System.out.println("这是fun方法");
		
	}

	@Override
	public void func() {
		System.out.println("这是func方法");
		
	}
	
}

       其中invoke方法是接口InvocationHandler定义必须实现的,它完成对真实方法的调用。我们来详细讲解一下InvocationHandler接口,动态代理是根据被代理的接口生成所有的方法,也就是说给定一个接口,动态代理会宣称“我已经实现该接口下的所有方法了”,那各位读者想想看,动态代理怎么才能实现被代理接口中的方法呢?默认情况下所有的方法返回值都是空的,是的,代理已经实现它了,但是没有任何的逻辑含义,那怎么办?好办,通过InvocationHandler接口,所有方法都由该Handler来进行处理,即所有被代理的方法都由Invocation Handler接管实际的处理任务。

 

如果对你有帮助,记得点赞哦~欢迎大家关注我的博客,我会持续更新,如果有什么问题,可以进群366533258一起交流学习哦~

 

  • 7
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

温柔狠角色

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值