最近在学php框架Laravel,发现里面有很多Facade,所以特地去学习了一下,发现原来是某个设计模式。所以写下来做个笔记。
例子
那么对应到编程之中我们写的某一个功能可能需要调用到很多类,如果后续维护者去维护这个功能的时候也需要清楚所调用的每一个类那时间成本太高,而且也不利于维护。各个类之间的联系太多,我们称之为耦合性过高。
那么能不能有一个中间类就是为了这个功能服务的,我们只需要把所需要调用的类的相关逻辑写在这个中间类之中就可以完成该功能。
我们就拿股票和基金举个例子,投资者可以同时买入卖出多个股票,或者投资者可以买卖基金实现对多个股票买入卖出。都可以实现对数个股票的买入卖出。
代码
我们先来看看投资者直接买卖多个股票的情况:
public class Main {
public static void main(String[] args) {
IStock stockA=new StockA();
IStock stockB=new StockB();
IStock stockC=new StockC();
stockA.Buy();
stockB.Buy();
stockC.Buy();
stockA.Sell();
stockB.Sell();
stockC.Sell();
}
}
class StockA implements IStock{
@Override
public void Sell() {
System.out.println("sell StockA ");
}
@Override
public void Buy() {
System.out.println("buy StockA ");
}
}
class StockB implements IStock{
@Override
public void Sell() {
System.out.println("sell StockB ");
}
@Override
public void Buy() {
System.out.println("buy StockB ");
}
}
class StockC implements IStock{
@Override
public void Sell() {
System.out.println("sell StockC ");
}
@Override
public void Buy() {
System.out.println("buy StockC ");
}
}
以上代码有三个股票类StockA,StockB,StockC,都实现了IStock接口。
可以见到如果需要买卖股票用户需要了解这三个股票,然后逐一操作。时间成本过高,而且跟每一个股票都有联系耦合性过高。
那么如果我们用一个基金Fund,把这些股票封装起来会是怎么样的呢?
public class Main {
public static void main(String[] args) {
Fund1 fund1=new Fund1();
fund1.bugFund();
fund1.sellFund();
}
}
class Fund1 {
IStock stockA = new StockA();
IStock stockB = new StockB();
IStock stockC = new StockC();
public void sellFund() {
stockA.sell();
stockB.sell();
stockC.sell();
}
public void bugFund() {
stockA.buy();
stockB.buy();
stockC.buy();
}
}
class StockA implements IStock {
@Override
public void sell() {
System.out.println("sell StockA ");
}
@Override
public void buy() {
System.out.println("buy StockA ");
}
}
class StockB implements IStock {
@Override
public void sell() {
System.out.println("sell StockB ");
}
@Override
public void buy() {
System.out.println("buy StockB ");
}
}
class StockC implements IStock {
@Override
public void sell() {
System.out.println("sell StockC ");
}
@Override
public void buy() {
System.out.println("buy StockC ");
}
}
这样只需要基金类了解每个股票,用户无需了解每个股票就可以完成买卖。
什么是外观模式(门面模式)
看完例子和代码,概括一下什么叫外观模式:
为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
上面是我自己画的图有点粗糙。
客户类可以通过Facade类使用到子系统的功能,而不用直接知道每个子系统的实现,甚至不用知道几个子系统的存在。而子系统在开发的时候不用使用Facade任何信息
与代理模式的区别
可能有些人看了觉得外观模式结构上跟代理模式有点相似。那么我们下面用一两句话说说代理模式与外观模式有什么不一样。
代理模式 用一个代理类代表另一个列的功能,不改变被代理类的功能。目的是控制被代理类的访问
外观模式 主要使用外观类隐藏系统复杂性 为客户类提供更简化的方法和对系统类方法委托调用。