浅谈proxy代理模式

耗尽温柔 提交于 2019-11-30 00:12:07

一、前言

代理是代替服务器去接受请求者的请求的中间人。我们也听说过代理服务器,它的作用的帮助客户端去请求客户端想要的资源,为什么要通过代理呢,那是因为客户端直接访问服务器会被拒绝(防火墙屏蔽),而代理服务器则可以直接访问服务器,客户端通过代理服务器,将请求的结果交给代理服务器,代理服务器对这些内容进行重组换成自己的标识(IP),并且将请求的结果返回给用户,这样做的弊端就是访问的速度大打折扣,但是总比没有强。

我们的代理模式就是这么干的,如果代理能够处理的东西(比如用户已经访问过的,服务器返回过来的没有过期的缓存),不用请求服务器了,直接返回给用户,而只有代理服务器不能处理的东西才会再次交给服务器去处理,当然这只是代理的一种策略,为了能够加快访问速度,这样代理服务器就代替我们去访问服务器了。

二、代码实例

本人去处理所有事情是非常麻烦的,特别是初始化的时候都非常的耗时,因此使用代理,不到必须自己出马的时候一直按兵不动,让代理去完成这些工作,这就是代理模式。

Printable接口:代理的同源性:

package designMode.proxy;

public interface Printable {
    public abstract void setPrinterName(String name);
    public abstract String getPirnterName();
    public abstract void print(String word);
}

Printer类:本人(相当于真正的服务器)

package designMode.proxy;

public class Printer implements Printable{
    String name;

    public Printer(String name) {
        this.name = name;
        heavyWork();
        System.out.println("生成打印机实例成功...");
    }

    private void heavyWork(){
        System.out.println("本人:"+name);
        try {
            Thread.sleep(5000);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }

    @Override
    public void setPrinterName(String name) {
        this.name=name;
    }

    @Override
    public String getPirnterName() {
        return name;
    }

    @Override
    public void print(String word){
        System.out.println("打印机"+name+"正在打印...");
        System.out.println(word);
        System.out.println("打印完成!");
    }
}

ProxyPrinter代理类:

package designMode.proxy;

public class ProxyPrinter implements Printable {
    String name;
    Printer printer = null;

    //代理能做的事情自己去做
    @Override
    public void setPrinterName(String name) {
        if(printer!=null){
            printer.setPrinterName(name);
        }
        this.name = name;
    }

    //代理能做的事情自己去做
    @Override
    public String getPirnterName() {
        return name;
    }

    //代理做不了的事情交给真正能做的(打印机)去做
    @Override
    public void print(String word) {
        check();
        printer.print(word);
    }

    private synchronized void check(){
        if(printer==null){
            printer = new Printer(name);
        }
    }
}

Main类:

package designMode.proxy;

public class Main {
    public static void main(String[] args) {
        Printable proxy = new ProxyPrinter();
        proxy.setPrinterName("江疏影");
        System.out.println("此时代理的名字为:"+proxy.getPirnterName());
        System.out.println("==遇到了代理处理不了的工作,通知服务器==");
        proxy.print("hello,world!");
        System.out.println("======================");
        proxy.setPrinterName("倪妮");
        System.out.println("此时代理的名字为:"+proxy.getPirnterName());
        proxy.print("hello,my country!");
    }
}

启动服务器很耗时(这里用睡眠5秒表示),那么使用代理服务器可以轻松处理一些事务(设置名字,获取名字),知道代理服务器无能为力的时候(print打印内容),代理服务器就会通知服务器去处理,从本例来看,因为使用了委托机制,将printer对象组合进来,但是printer是不知道代理的,它只是被启动了而已,这说明了什么?本人(printer)可以不做任何改动,就可以增加很多的代理去启动本人,这样非常有利于扩展,其实这里也使用了懒加载机制,看到只有到不得不使用的时候才生成被代理的实例,那么可不可以直接在代理模式中使用懒加载机制呢,答案是不利于扩展性,没有这种分而治之的思想好,这样的好处是很大的,在main中可以随意切换,同时能够定义相同的必须的接口。这种透明性是非常有益的,在很多模式中都有体现。

三、总结

代理模式是一种常见的模式,只在必须的时候生成实例,也分为很多种类,主要按照使用去分类的,比如本例的虚拟代理,以及其它的远程代理,访问控制代理等,我们主要理解代理的实现本质,代理的意义,以及手机用途。代理模式与装饰器模式比较类似,都是持有了同类或父类的引用(委托机制),并且在函数之中调用了同类的方法来加工与同类同名的本类的响应方法,但是也有区别,代理模式是为了减轻被代理人的工作,在不得已的时候再去打扰被代理人,而装饰器模式是为了产生新的功能,装饰原有的属性。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!