对于一个购物系统,通常需要几个子系统共同完成,它包括商品系统、购物车系统、订单系统、库存系统、支付系统、物流系统等等。
想想,这么多系统,作为开发者,写一个商品购买的方法,开发者需要熟悉每个系统的细节和每个系统的接口,同时包括系统之间的调用关系。子系统一两个还可以,如果系统多了,这不就是逼疯开发者么。
那么是否可以考虑定义一个上层接口,屏蔽这些系统之间的细节和复杂性。这个上层接口为子系统中较一般的使用,提供一个单一而简单的界面。 例如,调用一次购买行为,只需要调用一个接口,这个接口可以帮我们完成各个子系统之间的调用。
代码如下(代码即做示意,无发运行):
class ShoppingSystem { //商品系统
public function getShop($id) { //获取商品数据
return "My shop";
}
//其他方法
}
class StoreSystem { // 库存系统
public function checkStore($shopInfo) {
return "true/false"
}
public function deleteStore($shopInfo){ //减库存
return "减库存";
}
}
class ShoppingCar { //购物车系统
private $_list = [];
public function addShop($shop){
$this->_list[] = $shop;
}
public function getShop ($uid) {
return $this->_list;
}
}
class DealSystem { //订单系统
private $_deals = [];
public function createDeal($shop) { //创建订单
$this->_deals[] = $dealInfo
}
public function getDealInfo($deal) {
}
}
class PaySystem { //支付系统
public function getTotalMoney($deals) {
return "How Much";
}
}
统一接口:
class FacadeShoppingSystem {
//一般常规性接口
public function addCar($shopInfo) { //加入商品,先检查库存,然后添加到购物车
$ShoppingCar = new ShoppingCar();
$StoreSystem = new StoreSystem();
$ret = $StoreSystem->checkStore($shopInfo);
if($ret)
return $ShoppingCar->addShop($shopInfo);
return false;
}
//一般常规性接口
public function pay($deal) { //通过订单,支付支付
$DealSystem = new DealSystem();
$shopInfo = $DealSystem->getDealInfo($deal); //获取订单数据
$StoreSystem = new StoreSystem();
$ret = $StoreSystem->checkStore($shopInfo); //查找库存
if($ret) {
$PaySystem = new PaySystem(); //支付
return $PaySystem->getTotalMoney();
}
return false;
}
}
你看,通过FacadeShoppingSystem。我们屏蔽了需要系统之间的调用细节和复杂性,对于开发者而言,只需要了解FacadeShoppingSystem和对应的接口,至于系统之间怎么调用,怎么实现,调用方完全不需要关心。
而这就是今天的主角---外观模式
外观模式:简化一群类的接口,为子系统中的一组接口提供一个一致的界面, Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
将一个系统划分成为若干个子系统有利于降低系统的复杂性。一个常见的设计目标是使子系统间的通信和相互依赖关系达到最小。达到该目标的途径之一是就是引入一个 外观(facade)对象,它为子系统中较一般的设施提供了一个单一而简单的界面。
效果:
1) 它对客户屏蔽子系统组件,因而减少了客户处理的对象的数目并使得子系统使用起来更加方便。
2) 它实现了子系统与客户之间的松耦合关系,而子系统内部的功能组件往往是紧耦合的。松耦合关系使得子系统的组件变化不会影响到它的客户。 Facade模式有助于建立层次结构系统,也有助于对对象之间的依赖关系分层。 Facade模式可以消除复杂的循环依赖关系。这一点在客户程序与子系统是分别实现的时候尤为重要。
3) 如果应用需要,它并不限制它们使用子系统类。因此你可以在系统易用性和通用性之间加以选择