在当下的中国医疗环境下,病人去医院看病,一般都需要自己去挂号,然后去门诊,医生诊断完成之后,去划价,然后取药。这个流程是医院强加给病人的,病人为了看病就只能屈从于医院的这种安排,病人必须掌握这种流程,必须去一一做这些事情,想当一个合格的病人或者病人家属还挺不容易的。如果把看病作为一个子系统,挂号,门诊,划价,取药就是这个子系统中的具体模块,我们给出一个示意性代码:
/* 挂号的示意性代码 */
class Register {
public void doRigister() {
System.out.println("挂号成功,请去门诊候诊!");
}
}
/*诊断的示意性代码*/
class Diagnose {
public void doDiagnose() {
System.out.println("诊断完毕,请去划价!");
}
}
/*划价的示意性代码*/
class Charge {
public void doCharge() {
System.out.println("成功划价!");
}
}
/*取药的示意性代码*/
class Medicines {
public void doMedicines() {
System.out.println("红色药丸一天三次,一次三粒");
}
}
/*办理住院手续的示意性代码*/
class BeInHospital {
public void doIn() {
System.out.println("办理主元素后续");
}
}
/*使用CT检查的示意代码*/
class CT {
public void doCT() {
System.out.println("CT预约成功!");
}
}
病人对应着客户端:
/*在当前环境下,病人看病的流程*/
class Patient {
public static void main(String[] args) {
System.out.println("---来到医院,茫然无措,不知道该做什么,很是恐慌---");
//挂号
new Register().doRigister();
//门诊
new Diagnose().doDiagnose();
//划价
new Charge().doCharge();
//取药
new Medicines().doMedicines();
}
}
我们可以看到,为了完成看病的流程,客户端不得不去跟系统中的一个个模块去打交道,客户端必须得掌握各个模块,同时又很模块耦合的很紧密,一旦某个模块发生变化,客户端也要相应的改变。这可不是好的设计思路。用图来表示上面的例子会更直观一些
:
如果医院能派一个人来专门负责这些事情,或者提供一个绿色通道,只在一个地方办一次手续就完成了大部分的工作,如果是这样的话,那这个病人无疑会稍稍幸福一些。比如现在看病的流程是这样:
如果把上面的情形放到软件系统中就得到一个设计模式。
外观模式
有几个词需要说明一下,外观,视图,接口,当我们说外观、视图时不是说图形界面,而是说从外面看一个模块或者类时,我们能看到的内容,也许上面的话来形容接口更恰当,这里的接口不是指Java中的interface,而是Java中的类(或者接口)中暴露于外的内容,比如public的内容。还以上面的例子来说明,看病的具体流程就是系统中的一个模块,这些模块组合在一起就是一个子系统,外观定义了子系统的一个接口,也就是客户端通过外观能看到的内容。下面给出外观模式的定义:外观模式提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。
在没有使用外观模式的看病流程中有两个缺点:客户端必须要掌握很多模块;客户端和各个模块耦合紧密。使用了外观模式之后,客户端只要通过外观模式就能得到想要的内容,简化了学习难度,没有必要去掌握各个模块的细节。同时,外观还使客户端和各个模块解耦,在以后如果模块发生了变化,这些变化会被外观接口消化,客户端不会感知这种变化。外观模式的优点:提供统一的接口,简化访问;将客户与子系统解耦。这其实也是外观模式的本质:封装交互,简化调用。
使用外观模式来重写上面的例子,各个模块无需重写,我们需要增加一个外观类:
/*外观类,给客户端提供了一个视图,它应该是个单例类*/
public class Facade {
private static class Holder {
private static Facade instance = new Facade();
}
public static Facade getInstance() {
return Holder.instance;
}
/*缺省实现,对大多数人来说足够*/
public void doDefault() {
//挂号
new Register().doRigister();
//门诊
new Diagnose().doDiagnose();
//划价
new Charge().doCharge();
//取药
new Medicines().doMedicines();
}
public void doAll(boolean isCT) {
//挂号
new Register().doRigister();
//门诊
new Diagnose().doDiagnose();
if(isCT) {
new CT().doCT();
}
//划价
new Charge().doCharge();
//取药
new Medicines().doMedicines();
}
}
这个时候客户端在去调用就会很简单了:
class Patient {
public static void main(String[] args) {
System.out.println("---使用了外观模式之后---");
Facade facade = Facade.getInstance();
facade.doDefault();
//客户端还是可以直接使用各个模块
Medicines m = new Medicines();
m.doMedicines();
}
}
说明
外观接口没有给子系统增加任何新的功能,外观的目的是提供一个高层的接口,方便客户端调用,同时将模块与客户端解耦。对于客户端的请求,外观接口还是调用具体的模块去执行,它相当于一个代理。对于客户端而言,外观接口是子系统的一个视图,但是对于具体的模块而言,外观接口相当于客户端。也就是说,外观接口需要知道各个模块的存在,要掌握的它们的细节,但是具体的模块并不知道外观接口的存在。从语法上讲,可以在外观接口上增加一些额外的功能,但是这并不是外观接口的本意。
客户端可以绕过外观接口去访问具体的模块,以实现特别的功能。外观封装了一个缺省的实现,这个实现对于大多数人来说已经足够了,同时又简化了学习难度,只要知道外观接口就可以正确的使用子系统。但是对于有特别需求的客户而言,他们完全可以调用具体的模块进行更精确的控制。
可以为子系统实现一个以上的外观,但是过多的外观会引起混乱,客户端不知道到底该调用哪个外观,或者是直接调用具体模块。
最少知识原则(迪米特原则)
最少知识原则:只和你的密友谈话。它告诉我们要减少对象之间的交互,只留下几个“密友”。也就是说,当你在设计一个系统时,不管是任何对象 ,你都要注意它所交互的类有哪些,并注意它和这些类是怎么交互的。这个原则希望我们在设计中,不要让太多的类耦合到一起,免得修改系统中的一部分,会影响其他部分。就任何对象而言,在该对象的方法内,我们只应该调用属于以下范围的方法:
(i) 该对象本身的方法
(ii) 被当做方法的参数传递进来的对象的方法
(iii) 该对象持有对象的方法
(iiii)此方法创建的对象的方法
使用最少知识原则可以减少对象之间的依赖,但是会导致更多的包装类被引入进来。
在外观模式中就遵循了最少知识原则,客户端只有外观接口这一个朋友,成功的与具体模块解耦,这样子系统可以在不影响客户端的情况下进行修改,这些改变都会被外观模式所消化。
使用场景
1)为一个复杂的子系统提供一个简单的接口
2)提供子系统的独立性,将子系统与其他的部分解耦
3)在层次系统中,可以使用外观模式定义每一层的入口
4)在维护旧系统时,如果有新的功能依赖原来的模块,这个时候可以将外观模式应用到旧系统中,新的功能只从外观接口中获得功能,对旧系统的维护和修改不会影响新功能的调用。
外观模式提供了一个高层的接口,它帮助客户容易的调用子系统,同时将客户端与子系统解耦,它不会增加新的功能,客户端也可以绕过它去访问底层的模块,因为外观模式的存在,客户变得简单而又富有弹性。
转载请注明出处:喻红叶《Java与模式-外观模式》
分享到:
相关推荐
3. 结构型模式:包括适配器模式、桥接模式、组合模式、装饰模式、外观模式、享元模式和代理模式。这些模式关注于如何组织类和对象,以提高系统的灵活性和可扩展性。 4. 行为型模式:包括职责链模式、命令模式、解释...
JAVA-设计模式-结构型模式-外观模式
Java常用设计模式-外观模式 外观模式(Facade Pattern)是一种结构型设计模式,它提供了一个简单的接口来访问复杂系统中的子系统,从而隐藏了子系统的复杂性。外观模式属于对象型模式,它通过创建一个外观类,将...
在Java编程中,外观模式的应用广泛,尤其是在处理大型项目或者模块化开发时,能够极大地简化客户端与系统内部复杂组件的交互。 外观模式的核心思想是定义一个高层接口,这个接口封装了子系统的多个接口,客户端通过...
《Java与模式-清晰书签版》是一份包含多种Java设计模式详解的资源包,旨在帮助开发者深入理解和应用设计模式。这份资源集成了多种格式的文档,包括详细的文本描述、图表解析以及实际代码示例,使得学习过程更加直观...
这个资源"Java设计模式----通俗易懂版"显然是一个专门针对初学者或需要深入理解设计模式的开发者编写的指南。作者以形象生动的例子解释了23种经典的Java设计模式,使得复杂的概念变得更加易于理解。 首先,我们要...
外观设计模式为子系统中的一组接口提供了一个统一的接口。... - 外观模式为复杂的子系统提供了一个简化的接口。 3. **维基百科解释**: - 外观是一个对象,它为更大的代码体(如类库)提供了一个简化的接口。
设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段...
这个“JAVA设计模式-chm版”资源显然包含了关于Java设计模式的详细信息,便于理解和应用。设计模式是对常见问题的解决方案的标准化描述,它们在软件工程中起到了重要的作用,帮助开发者创建可维护、可扩展且易于理解...
包括但不限于适配器模式、桥接模式、组合模式、装饰模式、外观模式、享元模式和代理模式。每一种模式都有其独特的应用场景和解决问题的方法,如适配器模式用于让两个不兼容的接口能够协同工作,桥接模式用于将抽象与...
设计模式练习-外观模式厂-JAVA外观模式练习示例。
JAVA设计模式-day2,请的行业大能讲得课程,涉及:创建模式(5种: 1、 工厂方法模式(Factory Method); 2、 抽象工厂模式; 3、 单例模式(Singleton) • 4、 建造者模式(Builder); 5、 原型模式(Prototype...
- **外观模式**:为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。 - **代理模式**:提供一个代理对象来控制对真实对象的访问。这种模式通常用于远程代理...
- **外观模式**:为子系统提供一个统一的接口,使得这些子系统更容易被使用,简化了系统间的交互。 - **享元模式**:运用共享技术有效地支持大量细粒度的对象,减少内存占用,提高性能。 - **代理模式**:为其他...
本文件“Java设计模式-图解-附代码.doc”主要探讨了Java语言中的设计模式,分为创建型、结构型和行为型三大类。下面将对这些模式进行详细解释。 1. **创建型模式**: - **工厂方法**:提供一个接口用于创建对象,...
- 外观模式:为子系统提供一个统一的接口,使得子系统更加容易使用。 - 享元模式:运用共享技术有效地支持大量细粒度的对象,减少内存开销。 - 代理模式:为其他对象提供一种代理以控制对这个对象的访问。 3. ...
JAVA设计模式-原则和23种设计模式归纳总结 本资源主要介绍了JAVA设计模式的原则和23种设计模式的总结。设计模式是软件设计中的一种解决方案,能够使软件系统更加灵活、可维护和可扩展。本资源首先介绍了设计模式的...
5. **外观模式(Facade)**:为子系统提供一个统一的接口,使得子系统更加容易使用。`Facade`目录下的代码可能演示了如何简化复杂系统的接口,使其对外只有一个入口点。 6. **建造者模式(Builder)**:将复杂对象的...
在Java中,外观模式通常包含以下几个关键部分: 1. **外观类(Facade)**:这是模式的核心,它为客户端提供了一种统一的调用方式。外观类通常会持有对子系统类的引用,并负责将客户端的请求转发给相应的子系统类...