【设计模式】牛掰格拉斯的代理模式

代理的本质

无论任何时候,只要谈到设计模式,大脑中一定要蹦出这四个字“活学活用”。

要想对某个事物做到活学活用,必须要对它足够了解,甚至要剖析到本质才行。

总是会有些人说,我干嘛要知道原理,干嘛要去看源码?会用就行了。对于这种情况,我只有五个字相送,“你开心就好”。

不可否认,认识一个陌生事物,大部分情况还是要从定义开始。

代理模式:为某对象提供一种代理以控制对该对象的访问,从而限制、增强或修改该对象的一些特性。

如果对代理模式本身就很熟悉的人,一眼就明白什么意思,甚至连代码怎么写都会浮现在脑海中。

关键是对代理模式一点都不熟悉的人,看到定义后绝对一脸懵。下面通过简单的图形来揭开迷惑。

没有使用代理模式,如下图01:

“源”直接访问“目标”。

使用了代理模式,如下图02:

“源”访问代理,代理访问“目标”。

人群中一定会有两种声音:

1)设计模式是很高深莫测的东西,有这么简单吗?

2)这怎么没有代码实现啊?

来听听作者的看法:

1)高深莫测和简单不一定都是对冲的。幸福绝对是高深莫测的,那什么是幸福呢,最多的答案恐怕就是,“一亩土地两头牛,老婆孩子热炕头”。

多么简单朴实的答案,可惜,包括我在内的很多人都追求不到。主要原因是我们人为(主观)的把很多事情搞复杂了。下面这个事情可以说明这一点。

中秋节放假时到附近的一个小景区去看一看,我发现有一种果树的果子挂满枝头,又大又圆,让人看了之后特别有欲望,甚至垂涎欲滴,可惜没有一个人去摘。

我的第一反应就是果子肯定不能吃。过了一会儿,终于抑制不住好奇心,就找了一个比较矮的果树,摸了摸枝头上的果子。果然硬如磐石。

2)对于一上来就说代码实现的人,只能认为是你拥有了一把锤子之后,看什么都像钉子。

代码实现永远都是最后一步,但在它之前,要找出问题,分析问题,给出方案,论证方案可行性。如果这些都OK了,代码就是水到渠成的事了。

记住这句话:

认清原理,搞清本质,永远都是最重要的,不单单是在写代码上,在社会上依然如此。

那代理的本质是什么呢?就两个字,“加层”,即增加一(多)层。这就是本质。

像其它的什么“控制访问”啦,“增强或修改特性”啦,只不过是这个“层"产生的一些(副)作用罢了。

生活中充满着代理

虽然大部分人都没有参与过诉讼,但作为常识我们都知道,当事人可以通过协议把自己的一些权力授权给律师,律师就可以在法庭上行使这些权利,此时律师就是代理。

现在网购已成为生活的一部分,但是收快递却比较麻烦,因为通常家中无人。此时菜鸟驿站(或妈妈驿站)出现了,它帮我们签收和暂存包裹,所以它就是代理。

现在生活压力大,每个人都要上班,所以中午和下午都没有时间去接送自己上小学的孩子,此时只能选择午托,我们交了托费之后就等于给了它授权,它代替我们去接送孩子,可见午托也是代理。

还有各种产品的代理商,有大区代理,省级代理,市级代理,等等。还有就是微商/代购,微商自己没有货品,只是发发朋友圈,最终是别人发货。代购就更直接了,代替你去购买,然后再邮寄给你。

明星艺人都有自己的经纪人,可以替自己接一些活动,讨价还价,安排日程等。此时经纪人就是代理。还有大BOSS也会请一到多个秘书,来代替自己做一些事情。

可见,生活中充满着很多代理,他们以各种各样的形式存在着,发挥着各种各样的功能和作用,也确实解决了很多社会和生活的问题。

但从本质来看,代理大都以“层”的形式呈现,站在老板的前面,替老板做事情。

和计算机相关的代理

大部分人可能都听过这样一句话,凡是遇到不好解决的问题,大都可以通过加一层得到有效的解决。加的这个层很多时候和代理有关。

为了网络安全问题,可以加一层防火墙,防火墙虽然不完全是代理,但却用到许多代理的理论和技术。

为了扩充本地局域网络,可以加一层交换机或路由器,它用来代理和转发网络请求。还会有一些附带的其它功能。

为了平衡多个服务器的处理能力,我们在前面加一个请求路由层,也就是负载均衡器了,如Nginx,它可以代理请求,并按规则转发。

再说说CRUD,原来是我们写代码直接使用JDBC访问数据库,现在我们写代码使用的是ORM框架,ORM框架再使用JDBC去访问数据库。ORM框架可以看作是JDBC的代理。

我们可以看到,从硬件到中间件,再到程序框架,都有代理的影子。

和编程相关的代理

上面所说的代理,都是广义的代理,主要侧重于角色和功能。

一旦在编程中谈到代理,基本就是狭义代理了。除了广义代理的要求外,还要保持类型的兼容和“接口”的一致。

说白了就是需要被代理对象的地方,给它一个代理也可以。可以在被代理对象上调用的方法,在代理上也可以调用。

这个要求和代理模式中的要求是一样的。

如果被代理的对象是一个类。我们用Target表示。

class Target {

    public String getDateTime() {        return "2019-10-09"    }

}

为了保持类型兼容和接口一致,我们需要生成一个子类。

除此之外还要有被代理的对象,所以还需一个成员变量。

为了添加一些功能,通常需要重写一些方法。

class Proxy extends Target {

    private Target target;

    @Override    public String getDateTime() {        return target.getDateTime() + ", 星期三";    }

}

这样就生成了一个代理,在需要Target的地方换成Proxy也没有问题,而且还会在日期后面加上星期。

如果被代理的对象是一个接口。我们用ITarget表示。

interface ITarget {

    String sayHello(String name);

}
class Target implements ITarget {

    @Override    public String sayHello(String name) {        return "hello " + name;    }

}

此时我们只需实现接口即可(当然也可以生成子类),其它的保持不变。

class Proxy implements ITarget {

    private ITarget target;

    @Override    public String sayHello(String name) {        return target.sayHello(name) + ", long time no see.";    }}

这也是一个代理,同样可以使用Proxy代替Target,而且在原来问好的基础上增加了更多的话语。

由于类型兼容且接口一致,所以用户代码有时也不知道到底是对象本身还是它的代理,不过这通常并不重要。

代理的好处我们已经看到了,但是也有不好的地方,就是要写代理的代码,造成代码量增加。

这个问题已经通过动态代理解决了。在Java里比较有名的动态代理,就是JDK动态代理和CGLIB代理。这大家都知道了。

全文总结

代理的本质就是通过加一层来解决问题。类型兼容和接口一致只是限制条件而已。

代理有着广泛的应用,想想Spring的成功,代理贡献了多少,绝对功不可没。

仔细体会下“加层”的含义,在代码中和生活中,你会发现它真的很牛掰格拉斯。

>>> 玩转SpringBoot系列文章 <<<

【玩转SpringBoot】配置文件yml的正确打开姿势

【玩转SpringBoot】用好条件相关注解,开启自动配置之门

【玩转SpringBoot】给自动配置来个整体大揭秘

>>> 品Spring系列文章 <<<

品Spring:帝国的基石

品Spring:bean定义上梁山

品Spring:实现bean定义时采用的“先进生产力”

品Spring:注解终于“成功上位”

品Spring:能工巧匠们对注解的“加持”

品Spring:SpringBoot和Spring到底有没有本质的不同?

品Spring:负责bean定义注册的两个“排头兵”

品Spring:SpringBoot轻松取胜bean定义注册的“第一阶段”

品Spring:SpringBoot发起bean定义注册的“二次攻坚战”

品Spring:注解之王@Configuration和它的一众“小弟们”

品Spring:bean工厂后处理器的调用规则

品Spring:详细解说bean后处理器

品Spring:对@PostConstruct和@PreDestroy注解的处理方法

品Spring:对@Resource注解的处理方法

品Spring:对@Autowired和@Value注解的处理方法

品Spring:真没想到,三十步才能完成一个bean实例的创建

品Spring:关于@Scheduled定时任务的思考与探索,结果尴尬了

>>> 热门文章集锦 <<<

毕业10年,我有话说

【面试】我是如何面试别人List相关知识的,深度有点长文

我是如何在毕业不久只用1年就升为开发组长的

爸爸又给Spring MVC生了个弟弟叫Spring WebFlux

【面试】我是如何在面试别人Spring事务时“套路”对方的

【面试】Spring事务面试考点吐血整理(建议珍藏)

【面试】我是如何在面试别人Redis相关知识时“软怼”他的

【面试】吃透了这些Redis知识点,面试官一定觉得你很NB(干货 | 建议珍藏)

【面试】如果你这样回答“什么是线程安全”,面试官都会对你刮目相看(建议珍藏)

【面试】迄今为止把同步/异步/阻塞/非阻塞/BIO/NIO/AIO讲的这么清楚的好文章(快快珍藏)

【面试】一篇文章帮你彻底搞清楚“I/O多路复用”和“异步I/O”的前世今生(深度好文,建议珍藏)

【面试】如果把线程当作一个人来对待,所有问题都瞬间明白了

Java多线程通关———基础知识挑战

品Spring:帝国的基石

作者是工作超过10年的码农,现在任架构师。喜欢研究技术,崇尚简单快乐。追求以通俗易懂的语言解说技术,希望所有的读者都能看懂并记住。下面是公众号的二维码,欢迎关注!

(0)

相关推荐

  • 前端5大常见设计模式、代码一看你就懂!

    原创IT实战联盟2019-04-02 08:15:00 前言 今天主要介绍一下我们平常会经常用到的设计模式,设计模式总的来说有23种,而设计模式在前端中又该怎么运用呢,接下来主要对比较前端中常见的设计 ...

  • [书籍精读]《JavaScript设计模式与开发实践》精读笔记分享

    写在前面 书籍介绍:本书在尊重<设计模式>原意的同时,针对JavaScript语言特性全面介绍了更适合JavaScript程序员的了16个常用的设计模式,讲解了JavaScript面向对象 ...

  • 用工厂设计模式+策略什么模式,彻底干掉if else

    老哥哔哔叨 无论是人生还是代码,都面临着很多的选择,代码里面充斥着无数的if / else,人生不也是一样吗?无数的分岔路口,我们无法避免这些选择,但是我们可以更优美的去做选择-设计模式. 谈恋爱的烦 ...

  • PHP设计模式之代理模式

    PHP设计模式之代理模式 代理人这个职业在中国有另外一个称呼,房产经济人.保险经济人,其实这个职业在国外都是叫做房产代理或者保险代理.顾名思义,就是由他们来帮我们处理这些对我们大部分人来说都比较生疏的 ...

  • [PHP小课堂]PHP设计模式之代理模式

    [PHP小课堂]PHP设计模式之代理模式 关注公众号:[硬核项目经理]获取最新文章 添加微信/QQ好友:[DarkMatterZyCoder/149844827]免费得PHP.项目管理学习资料

  • 大话设计模式笔记(五)の代理模式

    举个栗子 故事是这样的... 一个小伙子喜欢上了隔壁班的一个妹子,但是又不认识,也害羞不好意思主动去说话,于是拜托了同样在这个班的一个朋友去传递自己想要送的礼物... 代码实现 该模式就不上什么简单实 ...

  • 深入理解设计模式(23):代理模式

    一.引言 我们都知道,数据库连接是很珍贵的资源,频繁的开关数据库连接是非常浪费服务器的CPU资源以及内存的,所以我们一般都是使用数据库连接池来解决这一问题,即创造一堆等待被使用的连接,等到用的时候就从 ...

  • 葛大爷那句"牛掰格拉斯"笑翻全场,"格拉斯"什么意思?

    果然,你大爷还是你大爷. "葛大爷"在目前大热的电影<我和我的祖国>里"北京你好"单元里的表演堪称完美. 葛优在影片中饰演一个叫"张北京& ...

  • 设计模式(十三)——代理模式

    设计模式(十三)——代理模式

  • 无废话设计模式(11)结构型模式--代理模式

    0-前言 代理模式定义:为其他对象提供一种代理以控制对这个对象的访问. 1-实现 1-1.简单UML图: 1-2.代码实现 //1.抽象父类 abstract class Actor { public ...

  • Java设计模式——代理模式

    代理模式 学习目标 掌握代理模式的应用场景和实现原理. 应用场景 保护目标对象:客户并不知道对象是如何实现具体业务功能的,只要调用代理对象的接口就行了. 增强目标对象:在实现目标对象的业务功能之前或者 ...

  • 设计模式之☞代理模式

    一.代理模式的作用 将主要业务与次要业务进行松耦合的组装 二.代理模式本质 监控行为的特征 例子: <input type="button" onclick="处理 ...