首页 > 编程知识 正文

设计模式代理模式以购房中介为例吗,房地产传统代理模式

时间:2023-05-05 00:19:19 阅读:252752 作者:354

超级链接: Java常用设计模式的实例学习系列-绪论

参考:《HeadFirst设计模式》

1.关于代理模式

代理模式是一种结构型模式。

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

本文以购房中介为场景来学习代理模式:

购房者可以直接找房主买房。如此做较累,因为买房之前要多次房屋筛选,买房之后要签订合同等等。购房者可以找房屋中介买房,购房者只需进行少量看房即可,中介将代劳筛选房屋和签订合同等事宜。房屋中介其实最终还是通过房主完成买房。 2.房主

房子最终属于房主,首先我们先定义房主接口和房主类。

被代理对象:接口:IHouseOwner

/** * <p>房主接口</P> * * @author hanchao */public interface IHouseOwner { /** * 房屋交易 */ void tradeHouse();}

被代理对象:类:HouseOwner

/** * <p>房主</P> * * @author hanchao */@Slf4jpublic class HouseOwner implements IHouseOwner { /** * 房屋交易 */ @Override public void tradeHouse() { log.info("房屋交易"); }} 3.无代理:直接买房 /** * <p>购房者</P> * * @author hanchao */@Slf4jpublic class HouseBuyer { /** * 直接找房主购房 */ public void buyHouseDirectly() { log.info("购房者花费大量时间用于筛选房屋...最终选定了一间房。"); new HouseOwner().tradeHouse(); log.info("购房者与房主签订售房合同。"); }}

直接买房是在太麻烦了,因为购房者花费大量时间用于筛选房屋,在决定买房之后,购房者还需与房主签订一系列的售房合同。

为了省事省心,购房者决定通过售房中介进行买房。

4.静态代理 4.1.静态代理:代理对象:类

这种方式,通过定义售房中介,直接代理房主类进行售房。

/** * <p>房屋中介:静态代理-代理对象是类</P> * * @author hanchao */@Slf4jpublic class HouseAgentByStaticForClass { /** * 被代理的对象:房主 */ private HouseOwner owner; public HouseAgentByStaticForClass(HouseOwner owner) { this.owner = owner; } /** * 房屋交易 */ public void sellHouse() { //前置操作 log.info("中介替购房者完成筛选房屋...最终选定了一间房。"); //售房 owner.tradeHouse(); //后置操作 log.info("中介替购房者完成与房主签订的售房合同。"); }}

下面是通过中介买房的流程。

/** * <p>购房者</P> * * @author hanchao */@Slf4jpublic class HouseBuyer { /** * 找中介买房:静态代理-代理对象:类 */ public void buyHouseByStaticProxyForClass() { //被代理对象:房主类 HouseOwner owner = new HouseOwner(); //代理对象 HouseAgentByStaticForClass houseAgent = new HouseAgentByStaticForClass(owner); //买房 houseAgent.sellHouse(); }} 4.2.静态代理:代理对象:接口

这种方式,通过定义售房中介,直接代理房主接口进行售房。

/** * <p>房屋中介:静态代理-代理对象是接口</P> * * @author hanchao */@Slf4jpublic class HouseAgentByStaticForInterface implements IHouseOwner { /** * 被代理的对象:房主 */ private IHouseOwner owner; public HouseAgentByStaticForInterface(IHouseOwner owner) { this.owner = owner; } /** * 房屋交易 */ @Override public void tradeHouse() { //前置操作 log.info("中介替购房者完成筛选房屋...最终选定了一间房。"); //售房 owner.tradeHouse(); //后置操作 log.info("中介替购房者完成与房主签订的售房合同。"); }}

下面是通过中介买房的流程。

/** * <p>购房者</P> * * @author hanchao */@Slf4jpublic class HouseBuyer { /** * 找中介买房:静态代理-代理对象:接口 */ public void buyHouseByStaticProxyForInterface() { //被代理对象:房主接口 IHouseOwner iHouseOwner = new HouseOwner(); //定义代理对象 IHouseOwner houseAgent = new HouseAgentByStaticForInterface(iHouseOwner); //买房 houseAgent.tradeHouse(); }} 4.3.静态代理的不足

可维护性差:

被代理对象与代理类一一对应,如果新增被代理对象,则需要新增代理类。被代理方法与代理方法一一对应,如果新增被代理方法,则需要新增代理方法。 5.动态代理 5.1.JDK动态代理:代理对象:接口

自定义调用处理器:实现InvocationHandler:HouseAgentByDynamicForJdk

/** * <p>动态代理:房屋中介</P> * * @author hanchao */@Slf4jpublic class HouseAgentByDynamicForJdk implements InvocationHandler { /** * 被代理的对象:房主 */ private IHouseOwner owner; public HouseAgentByDynamicForJdk(IHouseOwner owner) { this.owner = owner; } /** * 对售房进行代理 * * @param proxy 代理对象实例 * @param method 被代理的方法 * @param args 参数 * @return 返回值 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //前置操作 log.info("中介替购房者完成筛选房屋...最终选定了一间房。"); //售房 Object result = method.invoke(owner, args); //后置操作 log.info("中介替购房者完成与房主签订的售房合同。"); return result; }}

JDK动态代理实现步骤:

/** * <p>购房者</P> * * @author hanchao */@Slf4jpublic class HouseBuyer {/** * 找中介买房:JDK动态代理-代理对象:接口 */ public void buyHouseByDynamicProxyForJdk() { //被代理的对象:房主接口 IHouseOwner owner = new HouseOwner(); //被代理对象的接口加载器 ClassLoader classLoader = IHouseOwner.class.getClassLoader(); //被代理的接口的类型 Class[] classes = {IHouseOwner.class}; //代理时的调用处理器:房租中介 InvocationHandler proxyHandler = new HouseAgentByDynamicForJdk(owner); //代理对象 IHouseOwner proxy = (IHouseOwner) Proxy.newProxyInstance(classLoader, classes, proxyHandler); //代理售房 proxy.tradeHouse(); }}

JDK通过java.lang.reflect.Proxy类能够实现动态代理,其主要流程如下:

实现InvocationHandler接口,自定义自己需要的调用处理器:invocationHandler。获取被代理对象的接口加载器:classLoader。获取被代理的接口的类型:clazz[]。通过java.lang.reflect.Proxy的静态方法newProxyInstance(),以invocationHandler、classLoader和clazz[]为参数,生成代理对象。调用代理对象的代理方法。

**注意:**根据上述流程,可以确定JDK动态代理针对的是接口,而非类。

如何实现对类的动态代理呢?这就需要CGLib了。

5.2.CGLIB动态代理:代理对象:类

自定义方法解释器:实现MethodInterceptor:HouseAgentByDynamicForJdk

/** * <p></P> * * @author hanchao */@Slf4jpublic class HouseAgentByDynamicForCglib implements MethodInterceptor { /** * 被代理的对象:房主 */ private HouseOwner owner; public HouseAgentByDynamicForCglib(HouseOwner owner) { this.owner = owner; } /** * 对售房进行代理 * * @param obj 代理对象实例 * @param method 被代理的方法 * @param args 参数 * @param methodProxy 方法代理 * @return 返回值 */ @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws InvocationTargetException, IllegalAccessException { //前置操作 log.info("中介替购房者完成筛选房屋...最终选定了一间房。"); //售房 Object result = method.invoke(owner, args); //后置操作 log.info("中介替购房者完成与房主签订的售房合同。"); return result; }}

CGLIB动态代理实现步骤:

/** * <p>购房者</P> * * @author hanchao */@Slf4jpublic class HouseBuyer { /** * 找中介买房:CGLIB动态代理-代理对象:类 */ public void buyHouseByDynamicProxyForCglib() { //被代理的对象:房主 HouseOwner owner = new HouseOwner(); //CGLIB增强的代理类 Enhancer enhancer = new Enhancer(); //被代理对象的类型 enhancer.setSuperclass(HouseOwner.class); //定义代理时的方法解释器 MethodInterceptor methodInterceptor = new HouseAgentByDynamicForCglib(owner); //以回调方式设置代理行为 enhancer.setCallback(methodInterceptor); //创建代理对象 HouseOwner roomowner = (HouseOwner) enhancer.create(); //代理售房 roomowner.tradeHouse(); }}

JDK通过org.springframework.cglib.proxy.Enhancer类能够实现动态代理,其主要流程如下:

实现MethodInterceptor接口,自定义自己需要的方法解释器:methodInterceptor。创建CGLIB增强型代理类:enhancer。为enhancer设置被代理对象的类型:clazz。以methodInterceptor为参数,为enhancer设置回调方法。调用Enhancer#create()方法创建代理对象。调用代理对象的代理方法。

注意:CGLIB动态代理针对的是类。

使用CGLIB可以直接引用其依赖,也可以使用springframework的内置CGLIB。

CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。

6.实际应用场景 Struts2中的拦截器Interceptor。Spring中的AOP。AspectJ的实现。 7.总结

最后以UML类图来总结本文的售房中介场景以及代理模式。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。