外观模式简述
- 外观模式(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个统一的可以访问系统的接口。
- 这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性。
- 这种模式涉及到一个单一的类,该类提供了客户端请求的简化方法和对现有系统类方法的委托调用。
- 符合迪米特法则(最少知识原则):一个软件实体应当尽可能少的与其他实体发生相互作用。
- 又被称作门面模式。
介绍
意图:为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
主要解决:降低访问复杂系统的内部子系统时的复杂度,简化客户端与之的接口。
何时使用: 1、客户端不需要知道系统内部的复杂联系,整个系统只需提供一个"接待员"即可。 2、定义系统的入口。
如何解决:客户端不与系统耦合,外观类与系统耦合。
关键代码:在客户端和复杂系统之间再加一层,这一层将调用顺序、依赖关系等处理好。
应用实例: 1、炒股很麻烦,但又想赚钱,那么可以把钱交由基金公司打理,基金公司进行投资,个人只和基金公司打交道。
优点: 1、减少系统相互依赖。 2、提高灵活性。 3、提高了安全性。
缺点:不符合开闭原则,如果要改东西很麻烦,继承重写都不合适。
使用场景: 1、为复杂的模块或子系统提供外界访问的模块。 2、子系统相对独立。 3、预防低水平人员带来的风险。
注意事项:在层次化结构中,可以使用外观模式定义系统中每一层的入口。
实现:
步骤1:创建金融产品接口类
package com.ly.facade;
/**
* liyang 2020-08-15
* 金融产品接口
*/
public interface Financial {
void buy();
void sell();
}
步骤2:创建具体的金融产品实现金融接口类
package com.ly.facade;
public class AppleStock implements Financial {
@Override
public void buy() {
System.out.println("买入苹果股票");
}
@Override
public void sell() {
System.out.println("卖出苹果股票");
}
}
package com.ly.facade;
public class KFCStock implements Financial {
@Override
public void buy() {
System.out.println("买入KFC股票");
}
@Override
public void sell() {
System.out.println("卖出KFC股票");
}
}
package com.ly.facade;
public class NationalDebt implements Financial{
@Override
public void buy() {
System.out.println("买入国债");
}
@Override
public void sell() {
System.out.println("卖出国债");
}
}
package com.ly.facade;
public class Deposit implements Financial{
@Override
public void buy() {
System.out.println("买入银行存款");
}
@Override
public void sell() {
System.out.println("卖出银行存款");
}
}
步骤3:创建基金产品由于组合上述金融产品,也就是投资上述金融产品,对应外观模式的Facade类
package com.ly.facade;
/**
* liyang 2020-08-15
* 长城基金Great Wall Fund
* 包含以上所有金融产品
*/
public class GWFund {
private AppleStock appleStock;
private KFCStock kfcStock;
private NationalDebt nationalDebt;
private Deposit deposit;
public GWFund() {
appleStock = new AppleStock();
kfcStock = new KFCStock();
nationalDebt = new NationalDebt();
deposit = new Deposit();
}
public void buyGWFund() {
appleStock.buy();
kfcStock.buy();
nationalDebt.buy();
deposit.buy();
}
public void sellGWFund() {
appleStock.sell();
kfcStock.sell();
nationalDebt.sell();
deposit.sell();
}
}
步骤4:创建客户端进行测试,人买相应的基金即可,繁琐的类型组合交由基金公司去搞定。
package com.ly.facade;
/**
* liyang 2020-08-15
* 客户端测试,人买基金,基金去分配如何购买响应地金融产品
*/
public class Client {
public static void main(String[] args) {
System.out.println("--start---");
GWFund gwFund = new GWFund();
gwFund.buyGWFund();
System.out.println("-separate-");
gwFund.sellGWFund();
System.out.println("---end---");
}
}
结果:
--start---
买入苹果股票
买入KFC股票
买入国债
买入银行存款
-separate-
卖出苹果股票
卖出KFC股票
卖出国债
卖出银行存款
---end---
Process finished with exit code 0
总结:
- 基金的动态调仓,乃至增减或删减金融产品,由于在Facade类中聚合聚合了相关金融产品类,需要改动大量的代码,不符合OCP原则,但是装饰后,简化客户端与复杂的类的交互。
- 开发中常见的场景:频率很高,在哪都会遇到。各种技术框架中都有外观模式的使用。比如,JDBC封装后的,commons提供的DBUtils类,Hibernate提供的工具类,Spring JDBC工具类等。
- 自己写的代码中,为了方便其他人使用,使用外观模式进行封装。(时刻要有封装的意识)