外观模式
外观模式,为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
如图所示,客户端只需要通过外观类封装好的接口来调用子系统类的方法,而不用直接调用。这样可以封装好一些复杂的实现和调用。
子系统类如下
外观类与测试代码
public class Facade {
private SubSystemOne one;
private SubSystemTwo two;
private SubSystemThree three;
private SubSystemFour four;
public Facade() {
one = new SubSystemOne();
two = new SubSystemTwo();
three = new SubSystemThree();
four = new SubSystemFour();
}
public void methodA() {
System.out.println("\n方法组A() ---- ");
one.methodOne();
two.methodTwo();
four.methodFour();
}
public void methodB() {
System.out.println("\n方法组B() ---- ");
two.methodTwo();
three.methodThree();
}
public static void main(String[] args) {
Facade facade = new Facade();
facade.methodA();
facade.methodB();
}
}
外观模式适用情况
- 在设计初期阶段,应该要有意识的将不同的两个层分离,比如三层接口,数据层、业务层、表示层中,层与层之间建立外观类,可以为复杂的子系统提供一个简单的接口,使得耦合大大降低。
- 在开发阶段,子系统往往因为不断的重构演化而变得越来越复杂,会产生很多很小的类,给外部调用带来困难,增加外观类可以提供一个简单的接口,减少它们之间的依赖。
- 在维护一个遗留的大型系统时,可能这个系统已经非常难以维护和扩展,但因为要开发新的功能必须依赖于它。可以给新系统开发一个外观类,来提供设计粗糙或者高度复杂的遗留代码的比较清晰的简单接口,让新系统与外观对象交互,外观对象与遗留代码交互所有复杂的工作。
外观模式很好的体现了依赖倒转原则和迪米特法则。
依赖倒转原则
依赖倒转原则:高层模块不应该依赖底层模块,两个都应该依赖抽象。抽象不应该依赖细节,细节应该依赖抽象。
面向对象的好处:可维护、可扩展、可复用和灵活性好
PC可插拔对应面向对象的强内聚、送耦合。CPU是强内聚的,只有个别厂商能制造,却能在不同的PC上使用,因为他们规定了标准的接口。
高层模块如果依赖底层模块,会导致因为底层模块不能用影响高层模块,比如底层是访问数据库,高层是业务逻辑,如果数据库从MySQL换成Oracle,底层和高层模块读不能用了。如果它们都依赖抽象的接口,则只需修改访问数据库的模块,不需要修改业务模块。
收音机就是典型的耦合过度,只要收音机出故障,都很难修理。
依赖倒转其实可以说是面向对象设计的标志,用哪种语言来编写程序不重要,如果编写时考虑的都是如何针对抽象编程而不是针对细节编程,即程序中所有的依赖关系都是终止于抽象类或者接口,那就是面向对象的设计,反之男就是过程化的设计。
迪米特法则
迪米特法则(LoD),如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。
它强调的前提是在类的结构设计上,每一个类都应当尽量降低成员的访问权限,也就是说,一个类包装好自己的private状态,不需要让别的类知道的字段或行为就不要公开。其根本思想,是强调了类之间的松耦合。类之间的耦合越弱,越有利于复用,一个处在弱耦合的类被修改,不会对有关系的类造成波及,也就是信息的隐藏促进了软件的复用。
比如说,小王去公司报道,人事处小杨给他开了条子,指定让他去找IT部的小张给他安装新电脑。但小张恰好有事,IT部只有小李有空,但小李看到条子上写的小张就不管了。根据迪米特法则,此处应该将IT部门作为抽象对象,内部是由小张、小李或者是增加一个主管来分配任务都不需要外部知道,小王只需要向IT部门这个抽象对象提出安装电脑的要求就可以了。