小时候快过春节了,爸妈都要给我们一身新,那时候有意思了,我们全家浩浩荡荡,去一个店买完衣服,再到另一个店挑鞋子,还要辗转换几家店子去选玩具。我妈妈又喜欢砍价,每次讲下一块钱她都眉开眼笑,似乎很有成就感。这一逛一讲,基本上一天就过去了,折腾的人受不了。那时候我就想啊,要有家综合型店子能够卖所有我需要的东西,还不许还价。呵呵,那我就开心了。这个呢,就是我们今天要讲的主题:门面模式。
出处:http://blog.csdn.net/lenotang/article/details/2593421
先来看看生活中门面模式的例子:
三国时,曹操接见匈奴使者,他觉得自己相貌不好,不足以用威仪震慑匈奴使者,于是命帅哥崔琰假扮自己,充当门面,曹操本人则提刀立于床头,装作侍从的样子。你看,曹操不愧一代英雄,这么早就会用门面模式了。
我们现在都喜欢用照相机,专业摄影人士总是选择自己调节光圈,调节焦距,开闪光灯,设置其它一些复杂的参数。而我们大部分人都只是使用自动拍照功能:取景,按快门就OK了,其它一切复杂的动作都被隐藏起来。这就是摄影上门面模式的运用。
还有很多门面模式的例子:新生报道,由父母打头阵,帮忙处理一系列繁杂的手续;医院就诊,安排接待员,由接待员负责代为挂号、划价、缴费、取药等;记者采访,通过新闻发言人,让记者们不用四处奔波,就可以获得政府各大职能部门最新最准确的信息等。
怎么样,现在你应该对门面模式有了基本的认识了吧。我们来看设计模式中的门面模式。
什么是门面模式?
门面模式(facade),又叫外观模式。要求一个子系统的外部与其内部的通信必须通过一个统一的门面(Facade)对象进行。门面模式提供一个高层次的接口,使得子系统更易于使用。
就如同医院的接待员一样,门面模式的门面类将客户端与子系统的内部复杂性分隔开,使得客户端只需要与门面对象打交道,而不需要与子系统内部的很多对象打交道。
门面模式的结构
这里,我们不知不觉的用到了一个法则:Law Of Demeter(中文名:迪米特法则)。
迪米特法则最初是由Han Holland1987年在美国Northeastern University做一个名为Demeter的项目时提出来的,这个法则有以下几个表达方式:
1、只和你的朋友们通信。
2、不要和陌生人讲话。
3、每一个软件单位对其他的单位都只有最少的知识,而且仅局限于那些与本单位密切相关的软件单位。
门面模式是代码重构以达到迪米特法则要求的一个强有力的武器。
下图演示了一个门面模式的示意性对象图:
在这个对象图中,出现了两个角色:
门面(Facade)角色:客户端可以调用这个角色的方法。此角色知晓相关的(一个或者多个)子系统的功能和责任。在正常情况下,本角色会将所有从客户端发来的请求委派到相应的子系统去。
子系统(subsystem)角色:可以同时有一个或者多个子系统。每一个子系统都不是一个单独的类,而是一个类的集合。每一个子系统都可以被客户端直接调用,或者被门面角色调用。子系统并不知道门面的存在,对于子系统而言,门面仅仅是另外一个客户端而已。
好啦,我们来做一个简单的JAVA实例,满足我儿时的心愿:
package com.wepull.facade;
/**
* @author leno 服装店
*/
public class Clothing {
public void getClothing() {
System.out.println(”买衣服”);
}
}
package com.wepull.facade;
/**
* @author leno 鞋店
*/
public class Shoes {
public void getShoes() {
System.out.println(”买鞋子”);
}
}
package com.wepull.facade;
/**
* @author leno 玩具店
*/
public class Toy {
public void getToys() {
System.out.println(”买玩具”);
}
}
public class Clothing
{
public Clothing getClothing()
{
return Clothing;
}
}
//电器类
public class Ele
{
public Ele getEle()
{
return Ele;
}
}
//首饰类
public class Jewelry
{
public Jewelry getJewelry()
{
return Jewelry;
}
}
/**————————–按照传统方式—————————*/
package com.wepull.facade;
/**
* @author leno 买主
*/
public class Buyer {
public void buy() {
// 先到服装店
Clothing clothing = new Clothing();
clothing.getClothing();// 购买到衣服
// 再到鞋店
Shoes shoes = new Shoes();
shoes.getShoes();// 购买到鞋子
// 还要去玩具店
Toy toy = new Toy();
toy.getToys();// 购买到玩具
}
}
public class Buy
{
//你需要到服饰店
Clothing c = new Clothing();
c.getClothing(); //购买到衣服
//接着去电器店
Ele c = new Ele();
c.getEle(); //购买到电器
//然后去首饰店
Jewelry c = new Jewelry();
c.getJewelry(); //购买到首饰
}
这样客户类和后台交互很频繁,很枯燥,而且你需要和一个一个商店类打交道,很麻烦,那就换一种方式 /**————————–按照门面模式—————————*/
package com.wepull.facade;
/**
* @author leno 购物中心
*/
public class ShopingCenter {
// 到购物中心的服饰店购买
public void clothingStore() {
Clothing clothing = new Clothing();
clothing.getClothing();// 购买到衣服
}
// 到购物中心的鞋店购买
public void shoesStore() {
Shoes shoes = new Shoes();
shoes.getShoes();// 购买到鞋子
}
// 到购物中心的玩具店购买
public void toysStore() {
Toy toy = new Toy();
toy.getToys();// 购买到玩具
}
}
好了,现在直接去购物中心,不用一家一家跑了
package com.wepull.facade;
/**
* @author leno 买主
*/
public class Buyer {
public void buy() {
ShopingCenter center = new ShopingCenter();
center.clothingStore();
center.shoesStore();
center.toysStore();
}
}
“金玉其外,败絮其中。”这句话对门面模式倒是可以解释。“金玉其外”指的就是门面,是调用者能看到的,是简单特定的接口。“败絮其中”指的就是复杂且全面的接口对象,里面有复杂的逻辑和结构,对调用者来说,是不可见的。如果调用者不通过门面类而直接调用子系统的接口,那就是很头疼的事。“一叶障目,不见泰山。”这就是门面模式的作用。好了,你又掌握了一种设计模式,继续修炼吧。