我们知道Google早就被墙了,所以FQ才能访问Google呢,这个“FQ”的过程就是一个代理的过程。“代理模式”在之前的博客中不止一次的提及过,之前的委托回调就是代理模式的具体应用。今天我们就从“FQ”中来认识一下代理模式。代理模式的定义如下:

代理模式:为另一个对象提供一个替身或占位符以控制对这个对象的访问。

首先说一下什么是“代理”吧,其实代理很好理解,你就把“代理”看成是二道贩子,说的好听点叫代理商。就是你买个东西,不从生产地直接买,而是通过二道贩子,三道贩子来进行购买,这些商贩就是代理商,也就是我们今天所说的代理。说的具体点,比如你要买棵萝卜,那么一般人不会去找菜农,然后给他们钱直接去地里薅萝卜。大部分人是通过商超来获取萝卜,这些商超就是所谓的萝卜代理商,也就是二道贩子。

那么在说一下什么是“FQ”吧,今天就拿Facebook为例。你是用户,Facebook网站就好比大萝卜,你直接去拔萝卜(直接访问FaceBook站点)不太现实,所以你得通过二道贩子(各种网络代理)来获取你想要的萝卜呢。可是你默认的代理商(GFW--长城防火墙)发现你购买萝卜不太单纯,所以就拒绝进行供货,这就是你访问的网站被墙了。可是你不甘心呢,家里兔子还等着吃萝卜呢。你得寻找新的代理商,此刻你就找到了Shadowsocks这个二道贩子。Shadowsocks没有什么估计的,他可以给你提供大萝卜,这就是FQ。Shadowsocks如何使用在此就不做过多的赘述了,自行Google。

言归正传,上面说这么多无非都是在解释什么是“代理”。今天我们就使用Swift代码来模拟上述的“FQ”过程,通过这个FQ过程来认识一下“保护代理模式”和“远程代理模式”,然后在结合着另一个实例来认识一下“虚拟代理模式”。进入今天的主题。

一、“FQ”的类图设计

其实在“FQ”这件事情上我们不关心如何去FQ,而是关心如何使用代理。在真正网络访问时,无论你是进行FQ访问,还是不FQ访问,都使用的“代理模式”。只不过FQ之前使用的是“保护代理模式”(GFW), 而FQ之后使用的是“远程代理模式”(因为今天的主题是“代理模式”,关于FQ我们先这么理解着,真正的网络代理要比这个复杂的多)。在该部分,基于我们今天这个FQ的场景,然后使用“代理模式”来设计GFW和Shadowsocks两种代理方式。下方就是我们所设计的FQ的类图,稍后会给出具体的代码实现。

在下方类图中绿框的部分是我们要访问的网站,其中有被墙的Facebook和Twitter,也有没被墙的Cnblogs。这三个Web站点都遵循一样的网络访问协议,此处我们定义了InternetAccessProtocol协议(接口)来模拟这些Web站点所遵循的网络协议。在InternetAccessProtocol网络访问协议中的response()方法是用来响应用户网络请求的,getId()方法用来返回该网站的唯一标示,也就是网站的域名。所有的Web站点都必须遵循该网络请求协议。

上面红框中是我们今天的核心部分,也就是网络代理部分。该部分声明了一个协议ProxyType,所有网络代理也都必须遵循该协议。因为网络代理是用来代理网络访问的,它作为用户与Web站点的中转者,对于用户来说该代理就如同真正的网站一样,随意ProxyType协议也必须的遵循上面定义的网络访问协议InternetAccessProtocol。在红框中有两个网络访问的代理,一个是ShadowsocksProxy,一个是GreatFirewall。

ShadowsocksProxy是远程代理,你在使用该远程代理时,你访问的网站不受限制,也就是说你可以访问Google、Twitter、Facebook这些网站,远程代理的态度是Open&Freedom的。远程代理只负责桥接,至于你访问的什么网站它不做关心,它只负责响应你的请求。而下方的GreatFirewall就不同了,GreatFirewall是一个保护代理,其中有一个blackList(黑名单),如下所示。blackList数组中记录的就是那些被墙的网站,只要是请求的网站在blackList中,你的请求是不会得到你请求网站的响应的。这也就是保护代理模式的功能,保护代理模式会添加一些权限的限制,会限制用户访问一些不安全的网站。

然后就是黄框中的Client了,在Client中依赖的是代理接口,也就是说Client只能依赖于代理进行网络访问。默认的代理就是GreatFirewall,GreatFirewall会屏蔽一些不能让你访问的网站。如果用户选择ShadowsocksProxy远程代理进行网络访问,就不受GreatFirewall的限制了,这也就是所谓的FQ。在下方Client类中就有两种上网方式,一种是Shadowsocks一种是GreatFireFirewall。有一点还是需要说明的是,真正的FQ不是不经过GreatFirewall,而是你的代理地址在GreatFirewall的白名单中,就是你可以通过GreatFirewall来访问的你的代理,然后你的代理是不经过GreatFirewall来访问你想要访问的Web站点的。该实例只是我们了解代理模式来模拟出来的实例,我们的重点在代理模式。

二、代码实现

上述给出了结构的设计,接下来我们就需要进行具体的代码实现了,我们在实现时仍然使用Swift语言。有了上面的类图设计,然后在给出代码实现似乎简单了许多。下方会分部分给出上述类图的代码实现,下方是一些代码的截图,更完整的实例请参见本博客后方github分享地址。

1.网络访问协议与Web站点的实现

下方就是网络访问协议与Web站点的具体实现。在InternetAccessProtocol网络访问协议中的response()方法用来响应用户的请求,getId()方法用来返回网站的域名。在InternetAccessProtocol协议的下方分别实现了三个web站点:Facebook、Twitter、Cnblogs。众所周知,前两个已经被墙了,所以如果你要想访问的话,你得FQ呢。web站点以及网络访问协议代码如下:

2. 两种代理的实现

首先我们先实现一个比较简单的,也就是远程代理。使用远程代理访问Web站点时没有一些不必要的限制,就是你访问什么网站,该远程代理就会请求什么网站并返回相应的信息。下方代码片段就是代理协议和远程代理ShadowsocksProxy的具体实现。在ProxyType代理协议中,setDelegate(delegate)方法用来设置代理,也就是用来设置访问的Web站点,ProxyType协议也同样遵循InternetAccessProtocol协议。在ShadowsocksProxy中的delegate成员变量就是用户要请求的Web站点,你访问的是A站点,那么此处的代理就是A站点的对象。在ShadowsocksProxy中的response()方法会请求delegate的response()方法,而代理中的getId()方法中则会返回当前远程代理的域名或者IP, 这一点很关键呢。具体代码实现如下:

接下来我们来实现我们的长城防火墙,也就是GreatFirewall。下方的代码实现就是GreatFirewall的实现,其中比上述的远程代理的实现多了一些东西,其中多了一项权限的控制。当你使用GreatFirewall来访问Web站点时,GreatFirewall首先会判断你所访问的Web站点在不在自己的黑名单中,也就是下方的blackList。如果你访问的Web站点在blackList中,就说明该站点被墙了,GreatFirewall就不会调用该Web站点的response(),所以用户就不会受到该网站的相应。相反,如果不在黑名单中,那么就会设置代理,然后就可以调用该Web站点的response()方法做出相应的响应,这也就是所说的“保护代理模式”。其实说白了,保护代理模式就是在远程代理上添加了一些权限的控制。具体代码实现如下。

三、Client与测试用例

上面实现完了Web站点,与Web站点的两个访问代理,下方我们就该实现Client用户的代码。然后在此基础上给出测试用例。下方的代码段就是我们的Client的代码实现。在Client中你可选择shadowsocks也可以选择使用greatFirewall。Client代码如下:

下方是我们的测试用例,以及该测试用例的输出结果。我们先使用远程代理访问Facebook是可以访问的,因为我们的远程代理没有添加任何限制。如果你通过GFW来访问Facebook,就访问不了,因为Facebook在GFW的黑名单中。但是你通过GFW访问远程代理服务器,然后在通过远程代理服务器去访问FaceBook是可行的。因为我们的远程代理服务器不在GFW的黑名单中,所以我们可以访问远程代理服务器,而我们的远程代理服务器是可以访问Facebook,所以我们可以访问Facebook。这也是测试用例中的第三段。代码以及输出结果如下所示。

四、虚拟代理

虚拟代理的作用就是为占用存储空间比较大的对象提供替身。当我们实例化大对象需要一定时间时(比如从网请求较大的图片),我们就可以使用虚拟代理提供一个对象的替身,等对象加载完毕后在使用我们这个真正的对象。因为虚拟代理较为简单,在此就不给出类图了,就直接给出代码实现吧。其实虚拟代理说白了也是代理模式,就是在大对象的使用者与大对象间添加了一层,这一层就是虚拟代理。

下方我们就以加载大图片为例,当我们加载比较大的图片时,为了不让用户等待,我可以先通过虚拟代理模式添加一个小的图片。然后在虚拟代理中将大图片加载完毕后我们在换回大的图片即可。下方我们创建了一个图片协议ImageType,然后创建了一个大的图片BigImage和一个小的图片SmallImage。SmallImage就作为BigImage未加载时的替身,当SmallImage加载完毕后我们就不使用SmallImage,而使用BigImage。而这一系列的替换的过程交给我们的虚拟代理来处理。

下方代码段中的BigImageProxy就是我们的虚拟代理。BigImageProxy也遵循于ImageType协议,对于用户来说,BigImageProxy的用法与普通的图片是一样的。在BigImageProxy中的loadImage()方法是我们虚拟代理的核心。在调用虚拟代理中的loadImage()方法时,如果BigImage已被实例化,就会调用loadImage()方法,如果BigImage没有实例化,那么就会调用SmallImage中的loadImage()方法,并且对BigImage进行实例化,并将虚拟代理中bigImage的状态设置为正在初始化状态。具体实现代码如下所示:

下方代码段就是上述虚拟代码的测试用例。ImageClient依赖的是ImageType协议,所以其中的image成员变量可以是真正的图片,也可以是我们的虚拟代理。虚拟代理对象的使用方式与普通图片的使用方式一致,测试用例如下所示:

今天我们的博客中就介绍了三种代理模式:远程代理模式、保护代理模式、虚拟代理模式。远程代理访问是控制访问远程对象,保护代理是基于权限的资源访问,虚拟代理是控制访问创建开销大的资源。

上述代码示例仍然会在github上进行分享,分享地址为:https://github.com/lizelu/DesignPatterns-Swift

设计模式(十三):从“FQ”中来认识代理模式(Proxy Pattern)的更多相关文章

  1. 设计模式系列之代理模式(Proxy Pattern)——对象的间接访问

    说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修炼之道)>一书的阅读笔记.个人感觉这本书讲的不错,有兴趣推荐读一读.详细内容也可以看看此书作者的博客https:/ ...

  2. 乐在其中设计模式(C#) - 代理模式(Proxy Pattern)

    原文:乐在其中设计模式(C#) - 代理模式(Proxy Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 代理模式(Proxy Pattern) 作者:webabcd 介绍 为 ...

  3. 设计模式 - 代理模式(proxy pattern) 未使用代理模式 具体解释

    代理模式(proxy pattern) 未使用代理模式 详细解释 本文地址: http://blog.csdn.net/caroline_wendy 部分代码參考: http://blog.csdn. ...

  4. 二十四种设计模式:代理模式(Proxy Pattern)

    代理模式(Proxy Pattern) 介绍为其他对象提供一个代理以控制对这个对象的访问. 示例有一个Message实体类,某对象对它的操作有Insert()和Get()方法,用一个代理来控制对这个对 ...

  5. 代理模式(Proxy pattern)

    代理模式(proxy pattern):作用:为其他对象提供一种代理,以控制对这个对象的访问.代理对象在客户端对象和目标对象之间起中介的作用. 代理模式涉及到的角色: 抽象角色:声明真实对象和代理对象 ...

  6. 设计模式——代理模式(Proxy Pattern)

    代理模式(Proxy),为其他对象提供一种代理以控制对这个对象的访问. UML图: 模型设计: Subject类: package com.cnblog.clarck; /** * Subject 类 ...

  7. 13.代理模式(Proxy Pattern)

    using System; namespace Test { //抽象角色:声明真实对象和代理对象的共同接口. //代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象, //同时代理 ...

  8. c#设计模式之代理模式(Proxy Pattern)

    引言 代理这个词语,大家在现实世界已经频繁的接触过,例如火车站代理售票点,因为这些代理售票点的存在,我们不必要去火车站的售票处就可以查询或者取到火车票.代理点本身是没有能力生产车票的,我们在代理处享受 ...

  9. C#设计模式——代理模式(Proxy Pattern)

    一.概述在软件开发中,有些对象由于创建成本高.访问时需要与其它进程交互等原因,直接访问会造成系统速度慢.复杂度增大等问题.这时可以使用代理模式,给系统增加一层间接层,通过间接层访问对象,从而达到隐藏系 ...

随机推荐

  1. IE10、IE11 User-Agent 导致的 ASP.Net 网站无法写入Cookie 问题

    你是否遇到过当使用一个涉及到Cookie操作的网站或者管理系统时,IE 6.7.8.9下都跑的好好的,唯独到了IE10.11这些高版本浏览器就不行了?好吧,这个问题码农连续2天内遇到了2次.那么,我们 ...

  2. 如何快速优化手游性能问题?从UGUI优化说起

    WeTest 导读   本文作者从自身多年的Unity项目UI开发及优化的经验出发,从UGUI,CPU,GPU以及unity特有资源等几个维度,介绍了unity手游性能优化的一些方法.   在之前的文 ...

  3. 阿里云学生优惠Windows Server 2012 R2安装IIS,ftp等组件,绑定服务器域名,域名解析到服务器,域名备案,以及安装期间错误的解决方案

     前言: 这几天终于还是按耐不住买了一个月阿里云的学生优惠.只要是学生,在学信网上注册过,并且支付宝实名认证,就可以用9块9的价格买阿里云的云服务ECS.确实是相当的优惠. 我买的是Windows S ...

  4. php批量删除

    php批量删除可以实现多条或者全部数据一起删除 新建php文件 显示数据库中内容: <table width="100%" border="1" cell ...

  5. css_02之盒模型、渐变

    1.框模型:盒模型,①对象实际宽度=左右外边距+左右边框+左右内边距 + width:②对象实际高度=上下外边距+上下边框+上下内边距 + height: 2.外边距:margin:取值:①top(上 ...

  6. Android MVP+Retrofit+RxJava实践小结

    关于MVP.Retrofit.RxJava,之前已经分别做了分享,如果您还没有阅读过,可以猛戳: 1.Android MVP 实例 2.Android Retrofit 2.0使用 3.RxJava ...

  7. iOS开发 判断当前APP版本和升级

    从iOS8系统开始,用户可以在设置里面设置在WiFi环境下,自动更新安装的App.此功能大大方便了用户,但是一些用户没有开启此项功能,因此还是需要在程序里面提示用户的 方法一:在服务器接口约定对应的数 ...

  8. 转:ORA-15186: ASMLIB error function = [asm_open], error = [1], 2009-05-24 13:57:38

    转:ORA-15186: ASMLIB error function = [asm_open], error = [1], 2009-05-24 13:57:38http://space.itpub. ...

  9. keepalive的不足,如何处理

    MySQL(或者其它服务)的keepalived高可用监控脚本 开发脚本需求:我们知道,keepalive是基于虚拟ip的存活来判断是否抢占master的机制的,但是如果我们做了MySQL的keepa ...

  10. mysql源码包手动安装、配置以及测试(亲测可行)

    笔记编者:小波/qq463431476博客首页:http://www.cnblogs.com/xiaobo-Linux/ 记下这篇mysql笔记,望日后有用! redhat6采用centos yum源 ...