java设计模式6——代理模式

java设计模式6——代理模式

1、代理模式介绍:

1.1、为什么要学习代理模式?因为这就是Spring Aop的底层!(SpringAop 和 SpringMvc)

1.2、代理模式的分类:

  • 静态代理
  • 动态代理

1.3、代理模式关系图(以租房子为例)

2、静态代理

2.1、角色分析:

  1. 抽象角色:一般会使用接口或者抽象类来解决
  2. 真实角色:被代理的角色
  3. 代理客户:代理真实角色。代理真实角色后,我们一般会做一些附属的操作
  4. 客户:访问代理对象的人

2.2、例1(租房子演示)

2.2.1、抽象角色实现(房东抽象类)

package com.xgp.company.结构性模式.代理模式.静态代理.Demo1;

/**
 * 租房
 */
public interface Rent {

    void rent();
}

2.2.2、真实角色实现(房东的实现类)

package com.xgp.company.结构性模式.代理模式.静态代理.Demo1;

/**
 * 房东
 */
public class Host implements Rent {

    @Override
    public void rent() {
        System.out.println("房东要出租房子!");
    }
}

2.2.3、不通过代理进行租房

package com.xgp.company.结构性模式.代理模式.静态代理.Demo1;

public class Client {
    public static void main(String[] args) {
        //直接找房东
        Host host = new Host();
        host.rent();
    }
}

运行结果:

房东要出租房子!

2.2.4、弊端

  1. 在实际的生活场景中,房东可能只卖房,而不负责租房
  2. 如果要提高租房子的成功率,必然还需要一些其他的服务,如:看房、谈价钱、签合同等,而这些房东并不想参与,因此产生了中介,也就是代理。

2.2.5、代理出现

package com.xgp.company.结构性模式.代理模式.静态代理.Demo1;

public class Proxy implements Rent {

    private Host host;

    public Proxy() {

    }

    public Proxy(Host host) {
        this.host = host;
    }

    @Override
    public void rent() {
        seeHouse();
        host.rent();
        fare();
        hetong();
    }

    //看房
    public void seeHouse() {
        System.out.println("中介代理看房");
    }

    //收中介费
    public void fare() {
        System.out.println("收中介费");
    }

    public void hetong() {
        System.out.println("签合同");
    }
}

2.2.6、通过代理来租房子

package com.xgp.company.结构性模式.代理模式.静态代理.Demo1;

public class Client {
    public static void main(String[] args) {
/*        //直接找房东
        Host host = new Host();
        host.rent();*/

        //通过代理去租房子
        //房东要租房子
        Host host = new Host();
        //代理
        //中介帮房东租房子,但是,中介一半都会有一些附属操作
        Proxy proxy = new Proxy(host);
        proxy.rent();
    }
}

运行结果:

中介代理看房
房东要出租房子!
收中介费
签合同

2.3、分析:

代理模式的好处

  1. 可以使真实角色的操作更加纯粹,不用去关注一些公共的业务。
  2. 公共的业务交给了代理角色去完成,实现了业务的分工。
  3. 公共业务发生扩展的时候,方便集中管理。

缺点:

  • 一个真实角色就会产生一个代理的角色,代码量翻倍,开发效率变低。

2.4、例1(增删改查业务的演示)

2.4.1、编写service的抽象类

package com.xgp.company.结构性模式.代理模式.静态代理.Demo2;

public interface UserService {
    void add();
    void del();
    void update();
    void query();
}

2.4.2、编写service的实现类

package com.xgp.company.结构性模式.代理模式.静态代理.Demo2;

/**
 * 真实对象
 */
public class UserServiceImpl implements UserService {
    @Override
    public void add() {
        System.out.println("增加了一个用户");
    }

    @Override
    public void del() {
        System.out.println("删除了一个用户");
    }

    @Override
    public void update() {
        System.out.println("更新了一个用户");
    }

    @Override
    public void query() {
        System.out.println("查询了一个用户");
    }
}

2.4.3、如果此时想不改变原有的代码,而增加方法日志打印的功能,此时代理诞生

package com.xgp.company.结构性模式.代理模式.静态代理.Demo2;

/**
 * 代理角色,增加日志的功能
 */
public class UserServiceProxy implements UserService {

    private UserService userService;

    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    @Override
    public void add() {
        userService.add();
        log("add");
    }

    @Override
    public void del() {
        userService.del();
        log("del");
    }

    @Override
    public void update() {
        userService.update();
        log("update");
    }

    @Override
    public void query() {
        userService.query();
        log("query");
    }

    public void log(String msg) {
        System.out.println("使用了" + msg + "方法!");
    }
}

2.4.4、编写客户端类,使用service的方法,并打印日志

package com.xgp.company.结构性模式.代理模式.静态代理.Demo2;

public class Client {
    public static void main(String[] args) {
        UserService userService = new UserServiceImpl();

        UserServiceProxy proxy = new UserServiceProxy();
        proxy.setUserService(userService);

        proxy.add();
        proxy.del();
        proxy.update();
        proxy.query();
    }
}

运行结果:

增加了一个用户
使用了add方法!
删除了一个用户
使用了del方法!
更新了一个用户
使用了update方法!
查询了一个用户
使用了query方法!

2.5、反思:在实际的业务中,横向开发的好处

可以保证原有代码的可行性,不会对软件原来的版本进行破坏,向过去兼容。

3、动态代理

3.1、动态代理的特点

  1. 动态代理和静态代理一样
  2. 动态代理的代理类是动态生成的,不是我们直接写的

3.2、动态代理实现方式的分类

  • 基于接口——JDK动态代理(本节需要讲述的方式)
  • 基于类:cglib
  • java字节码实现:javasist

3.3、需要了解的两个类

  • Proxy:代理类
  • InvocationHandler:调用处理程序类

具体的使用参照java的api

3.4、例1——房东租房的例子

3.4.1、房东的接口和实现类不变

3.4.2、实现自动生成代理的类

package com.xgp.company.结构性模式.代理模式.动态代理.Demo1;

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

/**
 * 等下我们会用这个类,自动生成代理类
 */
public class ProxyInvocationHandler implements InvocationHandler {

    /**
     * 被代理的接口
     */
    private Rent rent;

    public void setRent(Rent rent) {
        this.rent = rent;
    }

    /**
     * 获得一个代理
     * @return
     */
    public Object getProxy() {
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces(),this);
    }

    /**
     * 处理代理实例,并放回结果
     * @param proxy
     * @param method
     * @param args
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //用反射来执行方法
        seeHouse();     //调用代理自身的方法
        //动态代理的本质,就是使用反射机制来实现
        Object result = method.invoke(rent, args);
        fare();
        hetong();
        return result;
    }

    public void seeHouse() {
        System.out.println("中介带看房子!");
    }

    //收中介费
    public void fare() {
        System.out.println("收中介费");
    }

    public void hetong() {
        System.out.println("签合同");
    }
}

3.4.3、实现客户端使用代理来租房子

package com.xgp.company.结构性模式.代理模式.动态代理.Demo1;

public class Client {
    public static void main(String[] args) {
        //真实角色
        Host host = new Host();

        //代理角色
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        //通过调用程序处理角色,来处理我们要调用的接口对象
        pih.setRent(host);

        //放回代理类
        //这里的代理类就是动态生成的,我们并没有写他
        Rent proxy = (Rent) pih.getProxy();
        proxy.rent();
    }
}

运行结果:

中介带看房子!
房东要出租房子!
收中介费
签合同

3.5、例2——增删改查的例子

3.5.1、先来实现一个万能的代理生成类

package com.xgp.company.结构性模式.代理模式.动态代理.Demo2;

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

/**
 * 万能代理类
 */
public class ProxyInvocationHandler implements InvocationHandler {

    /**
     * 被代理的接口
     */
    private Object target;

    public void setTarget(Object target) {
        this.target = target;
    }

    /**
     * 获得一个代理
     * @return
     */
    public Object getProxy() {
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    }

    /**
     * 处理代理实例,并放回结果
     * @param proxy
     * @param method
     * @param args
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //用反射来执行方法
        //动态代理的本质,就是使用反射机制来实现
        Object result = method.invoke(target, args);
        log(method.getName());
        return result;
    }

    public void log(String msg) {
        System.out.println("使用了" + msg + "方法!");
    }
}

也就是将上一个例子的具体实现类——房东类,替换成Object类

3.5.2、UserService的接口和实现类不变

3.5.3、编写客户端类使用代理调用增删改查方法

package com.xgp.company.结构性模式.代理模式.动态代理.Demo2;

public class Client {
    public static void main(String[] args) {
        //真实角色
        UserService userService = new UserServiceImpl();
        //代理角色
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        pih.setTarget(userService);
        UserService proxy = (UserService) pih.getProxy();

        proxy.add();
        proxy.del();
        proxy.update();
        proxy.query();
    }
}

运行结果:

增加了一个用户
使用了add方法!
删除了一个用户
使用了del方法!
更新了一个用户
使用了update方法!
查询了一个用户
使用了query方法!

3.6、弊端分析:

虽然使用动态代理能够节省代码量,并且实现静态代理的全部优点。但是,动态代理的核心是反射技术,通过反射技术调用方法效率较大,因此也可能影响系统效率。

3.7、动态代理的好处

一个动态代理的是一个接口,一般就是对应的一类业务。

原文地址:https://www.cnblogs.com/xgp123/p/12308415.html

时间: 2024-10-08 10:30:16

java设计模式6——代理模式的相关文章

JAVA设计模式之代理模式

学编程吧JAVA设计模式之代理模式发布了,欢迎通过xuebiancheng8.com来访问 一.概述 给某一个对象提供一个代理,并由代理对象来完成对原对象的访问.代理模式是一种对象结构型模式. 二.适用场景 当无法直接访问某个对象或访问某个对象存在困难时可以通过一个代理对象来间接访问,为了保证客户端使用的透明性,委托对象与代理对象需要实现相同的接口. 三.UML类图 四.参与者 1.接口类:Subject 它声明了真实访问者和代理访问者的共同接口,客户端通常需要针对接口角色进行编程. 2.代理类

JAVA设计模式(3)----代理模式

1.  什么是代理模式?Proxy Pattern 代理模式定义:为其他对象提供一种代理以控制对这个对象的访问.在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用. 通俗的讲,代理模式就是我很忙没空理你,你要想找我可以先找我的代理人,代理人和被代理人继承同一个接口.代理人虽然不能干活,但是被代理的人可以干活. 这个例子中有水浒传中的这么几个人:名垂青史的潘金莲,王婆,西门大官人.西门庆想要找潘金莲,需要找王婆做代理.首先定义一个接口:Kin

Java 设计模式_代理模式(2016-08-19)

概念: 代理模式是对象的结构模式.代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用. 就是一个人或者机构代表另一个人或者机构采取行动.在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用. 类图: 在代理模式中的角色: ● 抽象对象角色:声明了目标对象和代理对象的共同接口,这样一来在任何可以使用目标对象的地方都可以使用代理对象. ● 目标对象角色:定义了代理对象所代表的目标对象. ● 代理对象角色:代理对象内部含有目标对象的

Java设计模式:代理模式(一)

问题的提出 现在生活中,常常在微信朋友圈里面看到代购的信息,你想在国外买什么,香港买什么,但是又懒得自己过去,于是常常委托别人帮忙买奶粉买那啥的.这类问题的缘由是因为客户和原产地没有直接的接触,所以需要一个代理(代购)的第三者来实现间接引用.代理对象可以在客户端和目标对象间起到中介作用,而且可以通过代理对象去掉客户不能看到的内容和服务或者添加客户需要的额外服务.代理模式是一种很好实现客户对象与代理对象分离的策略.其抽象UML图如下图 代理模式包含如下角色 ISubject:抽象主题角色,是一个接

Java设计模式——Proxy(代理)模式

Proxy(代理)模式为对象提供一个代理或者占位来控制对该对象的访问. 图像代理 使用Proxy模式的设计有时非常脆弱,它们依赖转发方法来调用其底层对象.转发可能会建立一个非常脆弱并且需要经常维护的设计. load()方法以JFrame对象为参数,用于在指定图像加载完毕之后进行回调.在执行load()方法的时候,它先以LOADING引用的图像对象为参数调用setImage(),然后重新绘制图形显示窗口,最后为自己启动一个单独的线程.而run()方法是在单独的线程中执行的,该方法根据构造器中指定的

JAVA设计模式之 代理模式【Proxy Pattern】

一.概述 给某一个对象提供一个代理,并由代理对象来完成对原对象的访问.代理模式是一种对象结构型模式. 二.适用场景 当无法直接访问某个对象或访问某个对象存在困难时可以通过一个代理对象来间接访问,为了保证客户端使用的透明性,委托对象与代理对象需要实现相同的接口. 三.UML类图 四.参与者 1.接口类:Subject 它声明了真实访问者和代理访问者的共同接口,客户端通常需要针对接口角色进行编程. 2.代理类:ProxySubject 包含了对真实(委托)对象(RealSubject)的引用,在实现

Java设计模式之代理模式(Proxy)

前言: 最近在研究Retrofit开源框架的时候,其主要核心代码是通过注解标示参数,动态代理模式实现具体接口,反射机制进行参数解析,最终实现发送请求.其实之前在学习Xutils源码的时候,Xutils 的task也是通过代理模式来访问的.为何要采用代理模式呢?有什么好处呢?抱着这些疑问!今天来学习总结一下. 什么是代理模式? 代理模式的定义:代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用.举例说明,就是一个人或者一个机构代表另一个人或者另一个机构采取行动.在一些情况下,一个

java设计模式之八代理模式(Proxy)

其实每个模式名称就表明了该模式的作用,代理模式就是多一个代理类出来,替原对象进行一些操作,比如我们在租房子的时候回去找中介,为什么呢?因为你对该地区房屋的信息掌握的不够全面,希望找一个更熟悉的人去帮你做,此处的代理就是这个意思.再如我们有的时候打官司,我们需要请律师,因为律师在法律方面有专长,可以替我们进行操作,表达我们的想法.先来看看关系图: 根据上文的阐述,代理模式就比较容易的理解了,我们看下代码: [java] view plaincopy public interface Sourcea

java设计模式之代理模式模式总结

定义:代理模式这种设计模式是一种使用代理对象来执行目标对象的方法并在代理对象中增强目标对象方法的一种设计模式. 解读定义: 1.代理对象和目标对象有共同的接口: 2.使用代理对象执行目标对象中的方法: 3.在代理对象中增强目标对象方法. 设计模式原则:开闭原则(对扩展开放,对修改关闭).一种好的设计模式甚至是架构,都是在不修改原有形态的基础上扩展出新的功能. 下面从代码角度理解代理模式: 要素:帅哥.美女.媒婆,那么美女害羞不好意思说话,这个时候媒婆就充当代理对象的身份.美女就是目标对象,并且还