我们知道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. Windows 7上执行Cake 报错原因是Powershell 版本问题

    在Windows 7 SP1 电脑上执行Cake的的例子 http://cakebuild.net/docs/tutorials/getting-started ,运行./Build.ps1 报下面的 ...

  2. Python标准模块--Unicode

    1 模块简介 Python 3中最大的变化之一就是删除了Unicode类型.在Python 2中,有str类型和unicode类型,例如, Python 2.7.6 (default, Oct 26 ...

  3. ASP.NET MVC5+EF6+EasyUI 后台管理系统(1)-前言与目录(持续更新中...)

    开发工具:VS2015(2012以上)+SQL2008R2以上数据库  您可以有偿获取一份最新源码联系QQ:729994997 价格 666RMB  升级后界面效果如下: 任务调度系统界面 http: ...

  4. Android权限管理之RxPermission解决Android 6.0 适配问题

    前言: 上篇重点学习了Android 6.0的运行时权限,今天还是围绕着Android 6.0权限适配来总结学习,这里主要介绍一下我们公司解决Android 6.0权限适配的方案:RxJava+RxP ...

  5. 读书笔记汇总 - SQL必知必会(第4版)

    本系列记录并分享学习SQL的过程,主要内容为SQL的基础概念及练习过程. 书目信息 中文名:<SQL必知必会(第4版)> 英文名:<Sams Teach Yourself SQL i ...

  6. MongoDB系列(二):C#应用

    前言 上一篇文章<MongoDB系列(一):简介及安装>已经介绍了MongoDB以及其在window环境下的安装,这篇文章主要讲讲如何用C#来与MongoDB进行通讯.再次强调一下,我使用 ...

  7. 【微信SEO】公众号也能做排名?

    [写于2016年8月] 最近,微信团队发出一则公告,开放公众号运营者一年内更改公众号名一次,这对不少名字起的奇葩名字(包括dkplus)的公众号来说是一件好事. 为什么说是好事呢?公众号名字直接关联到 ...

  8. Java

    2016-12-17  21:10:28 吉祥物:Duke(公爵)    Logo:咖啡(爪哇岛盛产咖啡)  An overview of the software development proce ...

  9. 性能测试工具 wrk 安装与使用

    介绍 今天给大家介绍一款开源的性能测试工具 wrk,简单易用,没有Load Runner那么复杂,他和 apache benchmark(ab)同属于性能测试工具,但是比 ab 功能更加强大,并且可以 ...

  10. 用命令行工具创建 NuGet 程序包

    NuGet.exe 下载地址 本文翻译自: https://docs.nuget.org/Create/Creating-and-Publishing-a-Package https://docs.n ...