原创

设计模式详解(五)--------代理模式

更多Python学习文章请点击

1. 相关

所谓的代理者是指一个类别可以作为其它东西的接口。代理者可以作任何东西的接口:网上连接、存储器中的大对象、文件或其它昂贵或无法复制的资源。

2. 个人理解

代理模式你不清楚的话,你肯定也接过生活中的代理商吧?代理模式与代理商的作用差不多。

我们搞一个代理商有什么用?

1.保护了供应商,不至于让客户直接与供应商扯皮

2.增加可操作空间,比如我想在你获取到商品的时候加价

3.减小互相之间的依赖性,在程序中体现为减小耦合

增加一个环节,当然也是有一定劣势的:

1.步骤过多,增加了交易的耗时

2.让交易看起来很复杂

那么如果你能看懂上面三点,你对代理模式的优缺点和运行模式就有一定理解了,下面我们来看一下程序中的代理模式。

3. 代理模式结构

在我们上面的举例中,旧大致体现出了代理模式的大致结构:服务商,代理商,客户端。

服务商:提供客户所需的实例

代理上:从服务商那里获取实例并提供一个接口给客户端,客户端从接口获取实例

客户端:获取并消费实例

思维导图

在这里插入图片描述

4. 实例

4.1. 实例场景

我们现在有一个计费方法,调起计费时需要请求第三方,有以下需求

不希望客户端能够直接获取这个计费实例,这样非常的不安全

希望客户端每次访问这个计费的时候,进行日志记录请求参数

希望获取计费结束后进行日志记录请求计费情况

4.2. 程序设计

公共接口:为了方便获取,我们需要先为所有服务商和代理提供一个公共接口,这个接口规定了我们根据服务商所提供 的所有服务。

服务商:在此示例,服务商只打印一个日志来代表获取实际计费服务。

代理商:继承公共接口,并通过接口方法获取服务商的实际服务;在获取计费之前和之后需要打印日志记录。

客户端:通过代理商获取计费服务并打印。

4.3. 公共接口(FeeInterface)

package cn.yzstu.proxy.feeinterface;

public interface FeeInterf {
   
    void doFee();
}

4.4. 服务商

package cn.yzstu.proxy.service;

import cn.yzstu.proxy.feeinterface.FeeInterf;

/** * @author baldwin */
public class FeeService implements FeeInterf {
   

    public FeeService() {
   
        System.out.println("新建一个FeeService!!!");
    }

    /** *@描述 服务商中的实际服务 *@方法名 doFee *@参数 [] *@返回值 void *@创建人 Baldwin *@创建时间 2020/5/11 *@修改人和其它信息 */
    public void doFee() {
   
        System.out.println("在Service中获取计费成功!!!");
    }
}

4.5. 代理商

package cn.yzstu.proxy.proxy;

import cn.yzstu.proxy.feeinterface.FeeInterf;
import cn.yzstu.proxy.service.FeeService;

/** * @author baldwin */
public class FeeProxy implements FeeInterf {
   

    /** * 代理商中与服务商接触 * */
    private FeeService feeService = new FeeService();

    public void doFee() {
   
        // 执行预操作
        preFee();
        // 通过实际服务商进行调起计费
        feeService.doFee();
        // 进行后操作
        postFee();
    }

    /** *@描述 请求Fee的预操作 *@方法名 preFee *@参数 [] *@返回值 void *@创建人 Baldwin *@创建时间 2020/5/11 *@修改人和其它信息 */
    private void preFee(){
   

        System.out.println("请求Fee之前的操作完成!!!");
    }

    /** *@描述 计费请求结束后的操作 *@方法名 postFee *@参数 [] *@返回值 void *@创建人 Baldwin *@创建时间 2020/5/11 *@修改人和其它信息 */
    private void postFee(){
   
        System.out.println("请求Fee之后的操作完成!!!");
    }
}

4.6. 客户端

package cn.yzstu.proxy;

import cn.yzstu.proxy.proxy.FeeProxy;

public class Client {
   
    public static void main(String[] args) {
   
        // 客户端中没有直接接触FeeService
        FeeProxy feeProxy = new FeeProxy();
        // 客户端调起计费
        feeProxy.doFee();
    }
}

4.7. 运行结果

/usr/lib/jvm/java-8-openjdk-amd64/bin/java ××××
新建一个FeeService!!!
请求Fee之前的操作完成!!!
在Service中获取计费成功!!!
请求Fee之后的操作完成!!!

Process finished with exit code 0

4.8. 小总结

代理模式的核心点就是客户端不与服务商接触。

5. 代理模式的一般场景

5.1. 服务安全

一般为了安全考虑,都不会让客户端接触核心服务,这样就可以用一个代理将客户端与核心服务隔离开。

5.2. 智能处理

就像我们刚才那样,可以在操作服务商的方法之前和之后都可以添加操作。在工作中的表现有一个就是操作数据库,可以在服务之前建立数据库连接,服务结束后断开连接。

5.3. 虚拟服务

这种情况在我们访问网页的时候经常发生,比如们要访问一个图片,但是这个图片非常大,可能会加载很久,这时就可以通过虚拟代理来先提供一个缩略图,等图片加载完成后再将原图展示。

5.4. 等等

6. 总结

其实最近在回顾之前写的关于设计模式的文章,我发现了一个问题,我所有的相关文章都是只有某一个模式的实例,这样其实显得文章很没有内容,就像代理模式,我在实际设计代码的过程中肯定不能单独使用,一定是配合其他设计模式一起使用,所以在考虑要不要出一个设计模式配合使用的合集。

代理模式也是一个很常用的模式,SpringAOP中大量使用了代理模式。

往期好文:

用Python每天给女神发一句手机短信情话

MySQL优化之explain

Spring源码分析-MVC初始化

春风得意马蹄疾,一文看尽(JVM)虚拟机

造轮子的艺术

源码阅读技巧

Java注解详解

教你自建SpringBoot服务器

更多文章请点击

正文到此结束