博客来源:http://wangym.iteye.com/blog/743944
近期参与项目研发,调用接口时遇一事不爽,比如在调C方法前必须得先调A方法,且成功后还得再调B方法,最后才能调C方法,而且接口还会有变更,突然说这中间还得再增加几步......
门面模式(亦称外观模式,Facade Pattern)的思想很好地解决了这一问题,当然,它的优点也不止如此。
场景举例
投递信件过程:首先写信的内容 -> 其次写信封 -> 把信放到信封里 -> 然后邮递
接口类:ILetterProcess
-
-
-
-
-
public interface ILetterProcess {
-
-
-
-
-
-
-
void writeContext(String context);
-
-
-
-
-
-
-
void fillEnvelope(String address);
-
-
-
-
-
void letterIntoEnvelope();
-
-
-
-
-
void sendLetter();
- }
/**
* @author xuanyin
*
*/
public interface ILetterProcess {
/**
* 首先写信的内容
*
* @param context
*/
void writeContext(String context);
/**
* 其次写信封
*
* @param address
*/
void fillEnvelope(String address);
/**
* 把信放到信封里
*/
void letterIntoEnvelope();
/**
* 然后邮递
*/
void sendLetter();
}
实现类:LetterProcess
(代码略)
场景类:Client
-
-
-
-
-
public class Client {
-
-
public static void main(String[] args) {
-
-
-
ILetterProcess letterProcess = new LetterProcess();
-
-
letterProcess.writeContext("context");
-
-
letterProcess.fillEnvelope("address");
-
- letterProcess.letterIntoEnvelope();
-
- letterProcess.sendLetter();
- }
- }
/**
* @author xuanyin
*
*/
public class Client {
public static void main(String[] args) {
// 创建一个处理信件的过程
ILetterProcess letterProcess = new LetterProcess();
// 开始写信
letterProcess.writeContext("context");
// 开始写信封
letterProcess.fillEnvelope("address");
// 把信放到信封,并封装好
letterProcess.letterIntoEnvelope();
// 跑到邮局把信塞到邮件,投递
letterProcess.sendLetter();
}
}
上述过程,与高内聚的要求相差甚远,更不要说迪米特法则、接口隔离原则。调用方首先得知道这四个步骤,而且还不能颠倒顺序。这在面向对象的编程中是极度地不适合的,它根本就没有完成一个类所具有的单一职责。更何况,如果信件多了就非常麻烦,每封信都要这样运转一遍。
模式演变
增加一邮局类,提供信件代发业务,只需把信件的必要信息告之,就代为发送,即提供以上四个步骤的一体化服务。
邮局类:PostOffice
-
-
-
-
-
-
public class PostOffice {
-
-
-
-
-
private ILetterProcess letterProcess = new LetterProcess();
-
-
-
-
-
-
-
-
public void sendLetter(String context, String address) {
-
-
- letterProcess.writeContext(context);
-
- letterProcess.fillEnvelope(address);
-
- letterProcess.letterIntoEnvelope();
-
- letterProcess.sendLetter();
- }
- }
/**
*
* @author xuanyin
*
*/
public class PostOffice {
/**
*
*/
private ILetterProcess letterProcess = new LetterProcess();
/**
* 写信,封装,投递,一体化了
*
* @param context
* @param address
*/
public void sendLetter(String context, String address) {
// 帮你写信
letterProcess.writeContext(context);
// 写好信封
letterProcess.fillEnvelope(address);
// 把信放到信封中
letterProcess.letterIntoEnvelope();
// 邮递信件
letterProcess.sendLetter();
}
}
注意,这个新增加的邮局类就是“门面对象”
增加邮局类后,在场景类中调用时就简单多了
场景类:Client
-
-
-
-
-
public class Client {
-
-
public static void main(String[] args) {
-
-
-
PostOffice postOffice = new PostOffice();
-
-
postOffice.sendLetter("context", "address");
- }
- }
/**
* @author xuanyin
*
*/
public class Client {
public static void main(String[] args) {
// 现代化邮局
PostOffice postOffice = new PostOffice();
// 写完内容和地址后邮局一体化代发,不必关心其中过程
postOffice.sendLetter("context", "address");
}
}
可以看到,在场景类中的调用简化了很多,只需要把信息提交过去就成了,不必再知道投递过程中的所有方法和顺序了。而且这样做的可扩展性还非常好,比如在非常时期,警察需要对信件进行安全检查,就可以按如下实现。
警察类:Police
-
-
-
-
-
-
public class Police {
-
-
-
-
-
-
-
-
public boolean checkLetter(ILetterProcess letterProcess) {
-
-
return true;
- }
- }
/**
*
* @author xuanyin
*
*/
public class Police {
/**
* 警察对信件进行检查
*
* @param context
* @return true检查通过|false检查不通过
*/
public boolean checkLetter(ILetterProcess letterProcess) {
return true; // or false
}
}
再看下当增加检查信件步骤后,邮局类的一些变更。
邮局类:PostOffice
-
-
-
-
-
-
public class PostOffice {
-
-
-
-
-
private ILetterProcess letterProcess = new LetterProcess();
-
-
-
-
-
private Police police = new Police();
-
-
-
-
-
-
-
-
public void sendLetter(String context, String address) {
-
-
- letterProcess.writeContext(context);
-
- letterProcess.fillEnvelope(address);
-
-
-
if (police.checkLetter(letterProcess)) {
-
-
- letterProcess.letterIntoEnvelope();
-
- letterProcess.sendLetter();
- }
- }
- }
/**
*
* @author xuanyin
*
*/
public class PostOffice {
/**
*
*/
private ILetterProcess letterProcess = new LetterProcess();
/**
*
*/
private Police police = new Police();
/**
* 写信,封装,投递,一体化了
*
* @param context
* @param address
*/
public void sendLetter(String context, String address) {
// 帮你写信
letterProcess.writeContext(context);
// 写好信封
letterProcess.fillEnvelope(address);
// 警察检查信件
if (police.checkLetter(letterProcess)) {
// 把信放到信封中
letterProcess.letterIntoEnvelope();
// 邮递信件
letterProcess.sendLetter();
}
}
}
增加警察检查信件这个逻辑后,并没有改动调用端的代码,也没有改变对外暴露的接口和方法,只是改变内部的处理逻辑,所以对调用端是透明的。这是一个非常棒的设计,这就是门面模式。
注意事项
一个接口类可以用多个门面
一般情况下,一个接口类只要有一个门面对象就足够了,但下列情况可以有多个:
1.门面对象已庞大到一定的程度:比如超过一定行数的代码,虽然都是非常简单的委托操作,也建议拆分成多个门面。拆分时可按功能拆分,比如一个数据库操作,拆分成查询门面对象,删除门面对象,更新门面对象等。
2.给接口类提供不同的访问路径:我的理解是,比如模块1通过门面对象A可以完整地访问所有逻辑,但模块2是受限制的,如果仍使用门面对象A,那是无法实现受限的。这时就需要新增门面对象B,提供模块2应得的方法。但在新增门面对象B时,无需重新实现。因在面向对象编程中,应尽量保持相同的代码只写一遍,避免以后修改时到处都要修改的杯具发生。如:
-
-
-
-
-
-
public class Facade2 {
-
-
-
private Facade1 facade1 = new Facade1();
-
-
-
-
-
public void methodB() {
-
this.facade1.methodB();
- }
- }
/**
*
* @author xuanyin
*
*/
public class Facade2 {
// 引用原有的门面
private Facade1 facade1 = new Facade1();
/**
* 因提供的方法在原有门面中已实现,故此处通过引用,无需重复实现
*/
public void methodB() {
this.facade1.methodB();
}
}
门面不参与接口类内的业务逻辑
门面对象只是提供一个访问接口的路径而已,不应该也不能参与具体的业务逻辑,否则就会产生一个倒依赖的问题:接口必须依赖门面才能被访问。如果在门面对象内有业务逻辑,则应建立一个封装类,封装完毕后提供给门面对象。
分享到:
相关推荐
门面模式(Facade Pattern)是软件工程中一种常用的结构型设计模式,它的主要目的是提供一个统一的接口,用来简化系统中一组复杂的接口或类的使用。这个模式将复杂的子系统接口封装在一个简单的门面对象中,使得...
7、门面模式FACADE PATTERN 8、适配器模式ADAPTER PATTERN 9、模板方法模式TEMPLATE METHOD PATTERN 10、建造者模式BUILDER PATTERN 11、桥梁模式BRIDGE PATTERN 12、命令模式COMMAND PATTERN 13、装饰模式...
门面模式(Facade Pattern)是一种设计模式,它在软件工程中扮演着简化复杂系统接口的角色。当一个系统或子系统包含大量类,并且客户端需要与这些类进行交互时,门面模式可以提供一个高层次的单一接口,使得客户端的...
### C++设计模式之门面模式(Facade Pattern) #### 一、门面模式概述 在软件工程领域,设计模式是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易...
外观模式(Facade Pattern)是设计模式中的一种结构型模式,其主要目的是为了简化客户端与复杂系统之间的交互。在C#编程中,外观模式通常用于减少客户端对子系统组件的依赖,提供一个统一的、高层次的接口,使得...
门面模式(Facade Pattern)是一种结构型设计模式,它的主要目的是为复杂的子系统提供一个统一且简单的接口,使得客户端能够更方便地与这些子系统交互,而无需了解子系统的内部实现细节。这种模式降低了客户端与子...
门面模式(Facade Pattern)是一种设计模式,它的主要目的是为了解决复杂系统中各个子系统的交互问题,提供一个简单的统一接口,使得客户端可以更轻松地使用这些子系统。这种模式在PHP开发中非常常见,特别是在处理...
门面模式(Facade Pattern)是软件工程中一种常用的设计模式,属于结构型模式。它提供了一个统一的接口,用来访问子系统中的一群接口。门面模式使得子系统的使用更为简单,同时也隐藏了子系统的复杂性,使得客户端...
门面模式(Facade Pattern)是软件工程中一种常用的设计模式,属于结构型模式。它为一个复杂的子系统提供了一个统一的接口,使得客户端可以更容易地使用这个子系统,而无需了解其内部的具体实现细节。在实际开发中,...
门面模式(Facade Pattern)是一种设计模式,属于结构型模式,它的主要目的是为了解耦复杂的系统,提供一个统一的入口,使得外部客户端可以更简单、更方便地与系统交互,而无需关注系统的内部实现细节。在门面模式中...
门面模式(Facade Pattern)是设计模式中的一种结构型模式,它的主要目的是为了解决复杂的系统接口提供一个简单易用的统一入口。在Java中,门面模式的应用可以帮助我们更好地组织代码,降低系统的耦合度,提高代码的...
门面模式(Facade Pattern)是一种结构型设计模式,它的主要目的是提供一个统一的接口,用来访问子系统中的一组接口。这个接口使得子系统更容易使用,同时也减少了客户端代码与子系统之间的耦合。门面模式通常用于...
门面模式(Facade Pattern)是一种设计模式,它在软件工程中扮演着简化复杂系统接口的角色。门面模式的核心思想是为一个复杂的子系统提供一个单一、简洁的接口,使得客户端可以更容易地理解和使用该子系统,而无需...
门面模式(Facade Pattern)是软件工程中一种常用的设计模式,属于结构型模式,它提供了一个统一的接口,用于访问子系统中的一组接口。在面向对象设计中,门面模式为子系统提供了更简单的接口,使得客户端可以更容易...
门面模式(Facade Pattern)是一种结构型设计模式,它的主要目的是提供一个统一的接口,用于客户端访问复杂的子系统。在大型软件系统中,通常会有很多个子系统,每个子系统都有自己的职责,而门面模式就是为了让...
门面模式【FACADE PATTERN】 适配器模式【ADAPTER PATTERN】 模板方法模式【TEMPLATE METHOD PATTERN】 建造者模式【BUILDER PATTERN】 桥梁模式【BRIDGE PATTERN】 命令模式【COMMAND PATTERN...
门面模式(Facade Pattern)是软件工程中一种结构型设计模式,它提供了一个统一的接口,用来访问子系统中的一组接口。这个统一的接口使得客户端不必了解子系统内部的复杂性,只需要与门面进行交互即可。门面模式简化...