大熊君说说JS与设计模式之(门面模式Facade)迪米特法则的救赎篇------(监狱的故事)

一,总体概要

1,笔者浅谈

说起“门面”这个设计模式其实不论新老程序猿都是在无意中就已经运用到此模式了,就像我们美丽的JS程序员一样不经意就使用了闭包处理问题,

1 function Employee(name) {
2     var name = name;
3     this.say = function () {
4         console.log("I am employee " + name) ;
5     } ;
6 }

代码中“say”是一个function,Employee也是一个function这就构成了一个闭包环境,其实多数我们都是如上的定义方式,也就潜移默化的使用了闭包,O(∩_∩)O~ 让我们继续回来,门面这个模式很容易理解见如下图

图中描述的很清晰,三个子系统彼此独立有自己的职责划分,从客户端的角度来看是不关心它们细节的,那么如何把这三个子系统与客户端做连线那?好的!!!这时文中的主角该亮相了,这就是门面模式它起到了一个统一入口的职责,

降低子系统之间客户端与实现化层之间的依赖性。当在构建一个层次化的系统时,也可以同过使用Facade模式定义系统中每一层的入口,从而简化层与层之 间的依赖关系。

文字可能会有些抽象但是慢慢来,一步步分析,现在假设有这么个场景,有两个以完善的插件模块,基于这个再做二次开发,我们想想这就和图中的场景很类似了,以下是模拟代码有助于理解

 1 function HelloWorld(){
 2     this.greetPlug = new GreetPlug() ;
 3     this.filterPlug = new FilterPlug() ;
 4     this.hello = function(name){
 5         if(!this.filterPlug.filter(name,"zhangsan")){
 6             this.greetPlug().say(name) ;
 7         }
 8     }
 9 } ;
10 function GreetPlug(){
11     this.say = function(what){
12         console.log("Hello," + what) ;
13     }
14 } ;
15 function FilterPlug(){
16     this.filter = function(what,not){
17         return (what === not) ? true : false ;
18     }
19 } ;

里面的HelloEorld就是相对于和门面接口,至于两外两个类是隐藏的,这就是大概的思路!再看两个应用例子加深理解,如下图

隐藏了DOM标准事件接口的细节,做了事件兼容的api。

这个大家就更熟悉了,jQuery的Ajax操作是大家平时操作相对来说比较频繁的,没错它也用到了门面模式,底层是低级api做支持,门面层通过不同参数划分职能!

二,门面与迪米特法则

迪米特法则(Law of Demeter)又叫作最少知识原则(Least Knowledge Principle 简写LKP),就是说一个对象应当对其他对象有尽可能少的了解,不和陌生人说话。英文简写为: LoD.

迪米特法则的核心观念就是类间解耦,弱耦合,只有弱耦合了以后,类的复用性才可以提高。

其实二者的关系很好理解,门面模式就是基于此法则衍生出来的解决方案,适用于特定场景的同一类问题的解决方案。下面再来看个例子,如下

现在有这么个场景------监狱内的犯人是不应该跟外面的人接触的,当然或许会有探亲的。这里的监狱就是类,里面的犯人就是类内部的信息,而监狱里的狱警就相当于迪米特法则的执行者

 1 function Inmates(){
 2     this.say = function(){
 3         console.log(‘狱友说:我们是狱友...") ;
 4     } ;
 5 } ;
 6 function Prisoners(){
 7     this.inmates = new Inmates() ;
 8     this.helpEachOther = function(){
 9         this.inmates.say() ;
10         console.log("家人说:你和狱友之间应该互相帮助...") ;
11     } ;
12 } ;
13 function Family(){
14     this.prisoners = new Prisoners() ;
15     this.visit = function(inmates,prisoners){
16         this.prisoners.helpEachOther() ;
17     } ;
18 } ;

看到这样的结果,是不是有些别扭,家人告诉犯人要与狱友好好相处,而狱友确冒出来说话。这显然越界了,因为监狱只允许家人探望犯人,而不是随便谁都可以见的

这里的家人和狱友有了沟通是违背迪米特法则的,所以我们需要将家人和狱友隔离开,对其进行重构

(1),定义家人类

1 function Family(){
2     this.prisoners = new Prisoners() ;
3     this.visit = function(prisoners){
4         console.log("家人说:") ;
5         this.prisoners.helpEachOther() ;
6     } ;
7 } ;

(2),定义犯人类

1 function Prisoners(){
2     this.inmates = new Inmates() ;
3     this.helpEachOther = function(){
4         console.log("犯人和狱友之间应该互相帮助...") ;
5         console.log("犯人说:") ;
6         inmates.weAreFriends() ;
7     } ;
8 } ;

(3),定义狱友类

1 function Inmates(){
2     this.weAreFriends = function(){
3         console.log(‘我们是狱友...") ;
4     } ;
5 } ;

(4),定义场景类

1 function Prison(){ 2 new Family().visit(new Prisoners()) ; 3 } ;

这样家人和狱友就分开了,但是也表达了家人希望狱友能跟犯人互相帮助的意愿。也就是两个类通过第三个类实现信息传递

三,概要总结

迪米特法则的总结:

迪米特法则不希望类直接建立直接的接触。如果真的有需要建立联系,也希望能通过它的友元类来转达。因此,应用迪米特法则有可能造成的一个后果就是:系统中存在大量的中介类,

这些类之所以存在完全是为了传递类之间的相互调用关系------这在一定程度上增加了系统的复杂度。有兴趣可以研究一下设计模式的门面模式(Facade)和中介模式(Mediator),

都是迪米特法则应用的例子。

门面模式的优点:

  松散耦合

  门面模式松散了客户端与子系统的耦合关系,让子系统内部的模块能更容易扩展和维护。

  简单易用

  门面模式让子系统更加易用,客户端不再需要了解子系统内部的实现,也不需要跟众多子系统内部的模块进行交互,只需要跟门面类交互就可以了。

  更好的划分访问层次

  通过合理使用Facade,可以帮助我们更好地划分访问的层次。有些方法是对系统外的,有些方法是系统内部使用的。把需要暴露给外部的功能集中到门面中,这样既方便客户端使用,也很好地隐藏了内部的细节。

哈哈哈,本篇结束,未完待续,希望和大家多多交流够沟通,共同进步(*^__^*) 嘻嘻……

时间: 2024-08-04 00:18:09

大熊君说说JS与设计模式之(门面模式Facade)迪米特法则的救赎篇------(监狱的故事)的相关文章

大熊君说说JS与设计模式之------代理模式Proxy

一,总体概要 1,笔者浅谈 当我们浏览网页时,网页中的图片有时不会立即展示出来,这就是通过虚拟代理来替代了真实的图片,而代理存储了真实图片的路径和尺寸,这就是代理方式的一种. 代理模式是比较有用途的一种模式,而且变种较多(虚代理.远程代理.copy-on-write代理.保护代理.Cache代理.防火墙代理.同步代理.智能指引),应用场合覆盖从小结构到整个系统的大结构, 我们也许有代理服务器等概念,代理概念可以解释为:在出发点到目的地之间有一道中间层,意为代理. 代理对象角色内部含有对真实对象的

大熊君说说JS与设计模式之------命令模式Command

一,总体概要 1,笔者浅谈 日常生活中,我们在看电视的时候,通过遥控器选择我们喜欢的频道时,此时我们就是客户端的角色,遥控器的按钮相当于客户请求,而具体执行的对象就是命令对象, 命令模式把一个请求或者操作封装到一个对象中.命令模式允许系统使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能. 先给个具体事例,如下: 1 function add(x, y) { return x + y; } ; 2 function sub(x, y) { return x -

大熊君说说JS与设计模式之------策略模式Strategy

一,总体概要 1,笔者浅谈 策略模式,又叫算法簇模式,就是定义了不同的算法,并且之间可以互相替换,此模式让算法的变化独立于使用算法的客户. 策略模式和工厂模式有一定的类似,策略模式相对简单容易理解,并且可以在运行时刻自由切换.工厂模式重点是用来创建对象. 策略模式应用比较广泛,比如:我们现在要定义数据交换格式,现有三种方案可选1,XML  2,JSON  3,CSV就可以使用策略模式实现. 这里我要强调的是------我们是针对不同数据源选择不同方案,针对的都是同一事物做相同意图的操作只是方案不

设计模式之门面模式---Facade Pattern

模式的定义 门面模式(Facade Pattern)也叫做外观模式,定义如下: Provide a unified interface to a set of interfaces in a subsystem. Facade defines a highet-level interface that makes the subsystem easier to use. 要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行.门面模式提供一个高层次的接口,使得子系统更易于使用. 类型 结构

大熊君说说JS与设计模式之------中介者模式Mediator

一,总体概要 1,笔者浅谈 我们从日常的生活中打个简单的比方,我们去房屋中介租房,房屋中介人在租房者和房东出租者之间形成一条中介.租房者并不关心他租谁的房.房东出租者也不关心他租给谁.因为有中介的存在,这场交易才变得如此方便. 在软件的开发过程中,势必会碰到这样一种情况,多个类或多个子系统相互交互,而且交互很繁琐,导致每个类都必须知道他需要交互的类,这样它们的耦合会显得异常厉害.牵一发而动全身,后果很严重,大熊很生气!~~~~(>_<)~~~~  好了,既然问题提出来了,那有请我们这期的主角-

大熊君说说JS与设计模式之------单例模式Singleton()

一,总体概要 1,笔者浅谈 顾名思义单例模式并不难理解,是产生一个类的唯一实例,在我们实际开发中也会使用到这种模式,它属于创建模式的一种,基于JS语言本身的语法特征, 对象直接量“{}”,也可以作为单例模式的一种表现形式,如下代码参考 1 function Foo(){ 2 this.bar = "Hello Singleton !" ; 3 } ; 4 var Singleton = { 5 instance : null , 6 getInstance : function(){

JS设计模式(门面模式)

<!--JS设计模式(门面模式)--> // 门面模式的概念:简化API接口 最经典的就是事件 // 做一件事情: 必须要调用2个函数分别是 a , b //案例:获得页面上多个元素并设置css样式 window.onload=function(){ setCss(["div1","div2","div3"],{ background:"blue", color:"#fff" }); } fun

设计模式之门面模式20170728

结构型设计模式之门面模式: 一.含义 门面模式也叫做外观模式,是一种比较常用的封装模式,其定义如下: 要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行,门面模式提供一个高层次的接口,使得子系统更易于使用. 通俗来说,门面模式注重"统一的对象",也就是提供一个访问子系统的接口,除了这个接口不允许有任何访问子系统的行为发生.也就是说,门面对象是外界访问子系统内部的唯一通道. 二.代码说明 1.主要有两个角色 1)门面角色 客户端可以调用这个角色的方法.此角色知晓子系统的所有功能

设计模式之门面模式(facade)

1.定义 门面模式(Facade Pattern)也叫做外观模式,是一种比较常用的封装模式.要求一个子系统的外部与其内部的通讯必须通过一个统一的对象进行.门面模式提供一个高层次的接口,使得子系统更易于使用. 2.通用类图 Facade门面角色:客户端可以调用这个角色的方法.此角色知晓子系统的所有功能和责任.一般情况下,本角色会将所有从客户端发来的请求委派到相应的子系统中去,也就是说该角色没有实际的业务逻辑,只是一个委托类. subsystem子系统角色:可以同时有一个或多个子系统.每个子系统都不