• 設計模式:外觀設計模式 (一)


    這個系列為 PHP 模式設計
    該系列共分為六章節,以PHP代碼為示例講述模式設計的代點。



    面向對象編程時,當人們向你提起設計模式,你一定會有疑問:為什么我要在編程的過程中用到設計模式?不用這些模式代碼不是跑的也挺好。


    我總是這樣反駁這疑問:您是愿意住在豪華裝修的套房內,還是就只有四面墻支起的房子內?畢竟,這兩個都滿足我們住的需求。


    一般來說,我們會選擇豪華套房了。因為這樣的房子會提供比較好的基礎設施,同時維護成本相對較低。即使需要維修之時,這類房子也已經具備了很好的基礎條件,相對來說,維修的麻煩會少很多。


    對于程序來說是一樣的道理: 使用了設計模式的代碼將會更容易理解,容易維護,并且容易擴展。


    這個系列的教程中,我們會涉及到一些不同的設計模式,都可以很好的應用到我們的程序中去。您也會了解到這些模式的優缺點,以及各種影響我們在不同環境下使用他們的主要國素。


    我們將在這個系列的教程里采用 PHP 做為演示設計模式的語言; 當然,您應該明白,設計模式本身是一個通用概念可以應用在任何一種程序語言中-您唯一要做的只是改成您所擅長的語言的具體語法。


    設計規則被分成了四個大類:

    產生模式

    結構模式

    行為模式

    并發模式

    在本節教程里,我們打算了解一下外觀設計模式。他本來是屬于結構設計的大范疇之內了,因為外觀設計模式所要解決的問題就是如何更好的組織代碼讓他更清晰明了,并且能保護代碼在很長時間內都能很好的維護。

    外觀設計模式

    統一建模語言

    問題

    讓我們假設您有一些操作需要按順序執行,同時這些一樣的行動會在您的程序中多個不同的地方被調用。您不得不把同樣的代碼,一遍遍的拷貝到不同的地方。 歷經千辛您終于完成了這浩大的工程,可沒過幾天,您發現得修改下這段小代碼。

    問題出來了,不是嗎?這意味著您得去修改每個引用了這段代碼的地方了,人世間還有比這更痛苦的事嗎?

    解決

    做為解決方案,您所要做的就是創造一個主控制器,用這個控制器來處理所有的重復引用的代碼。 從視圖的調用點來看,我們更愿意通過所提供的參數去調用這個主控制器以完成我們要求的動作。

    現在我們如果需要修改這個流程,我們只需要修改主控制器里面的代碼,而不用在整個程序里面去修改這段被多次引用的代碼了。

    例子

    在這個教程里,讓我們選取一個實例來闡明這個原則。假設您朋友需要您的幫助,幫他計劃整個婚禮流程。如果所有的事兒都是您一個人做,想象一下您得負責多少事吧!用這種方式舉辦婚禮,太容易出錯了,也極大的提高了因您漏掉某件事而完全破壞了您朋友婚禮的機會。

    所以,在處理這樣的事,您不應該自己來做這件事,而應該是找到一個專業的婚禮策劃師,以確保婚禮上的每件事都能做好,并且所有的事情都是可控的,以減少整個流程的出錯機會。

    這樣,您就扮演的是一個客戶來發起這件事,而婚禮策劃師就會做為一個外觀模式來為您工作,他會按照您所決定的方向來完成整件工作的。

    代碼示例

    我們在這小節來看看更多的例子,這些例子已經被很普遍的運用到了網站開發建設中了。 我們來研究一下如果把一個外觀設計模式布署到我們的產品結賬頁面里去。 但是在我們研究這好代碼之前,讓我們先看一下有問題的代碼。

    一個簡單的結賬流程包括下面幾步:


    1. 1. 把商品加入購物車
    2. 2.     計算運費
    3. 3.     計算折扣價格
    4. 4.     生成訂單


    問題代碼:

    // Simple CheckOut Process
    $productID = $_GET['productId'];
    $qtyCheck = new productQty();
    if($qtyCheck->checkQty($productID) > 0) {
    // Add Product to Cart
    $addToCart = new addToCart($productID);
    // Calculate Shipping Charge
    $shipping = new shippingCharge();
    $shipping->updateCharge();
    // Calculate Discount Based on
    $discount = new discount();
    $discount->applyDiscount();
    $order = new order();
    $order->generateOrder();
    }

    在上面的代碼里,您會發現在結賬過程里您需要生成很多的對象以協助您完成整個結賬過程。 所以您可以想象一下,您需要在程序的很多地方布署這樣的代碼來完成您的操作。 如果按現在這做法,一旦程序需要修改,那問題就來了。最好的辦法就是讓這些變化只做一次性修改就好了。

    解決

    我們利用外觀設計模式,重新寫了上面的代碼,以使該代碼更具維護性和可擴展性。

    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    classproductOrderFacade {
    public$productID='';
    publicfunction__construct($pID) {
    $this->productID =$pID;
    }
    publicfunctiongenerateOrder() {
    if($this->qtyCheck()) {
    // Add Product to Cart
    $this->addToCart();
    // Calculate Shipping Charge
    $this->calulateShipping();
    // Calculate Discount if any
    $this->applyDiscount();
    // Place and confirm Order
    $this->placeOrder();
    }
    }
    privatefunctionaddToCart () {
    /* .. add product to cart ..  */
    }
    privatefunctionqtyCheck() {
    $qty='get product quantity from database';
    if($qty> 0) {
    returntrue;
    }else{
    returntrue;
    }
    }
    privatefunctioncalulateShipping() {
    $shipping=newshippingCharge();
    $shipping->calculateCharge();
    }
    privatefunctionapplyDiscount() {
    $discount=newdiscount();
    $discount->applyDiscount();
    }
    privatefunctionplaceOrder() {
    $order=neworder();
    $order->generateOrder();
    }
    }

    現在我們已經讓我們的產品定單的外觀設計模式準備好了,接下來的要做的全部工作也就是在調用這段代碼的地方寫上那么幾行建立對接渠道的代碼即可,想想這也比以前把大段代碼不斷拷貝要好太多了。


    我們也把要建立對接渠道的代碼示例放在了下面,您自己可以和以前那種流程方式做下比較了。


    1
    2
    3
    4
    5
    6
    // Note: We should not use direct get values for Database queries to prevent SQL injection
    $productID=$_GET['productId'];
    // Just 2 lines of code in all places, instead of a lengthy process everywhere
    $order=newproductOrderFacade($productID);
    $order->generateOrder();

    想象一下現在您要修改您的產品結賬流程。其實您只要修改結賬的外觀設計模式代碼就好了。其它地方只是接口調用,完全可以不用管了。


    結語


    我們可以這樣說外觀設計主要是被運用在這樣的條件下,您的一段接口代碼會在整個程序中被多次調用,就如同前面我們所提示的婚禮策劃者一樣,他就象一個外觀設計模式一樣工作,協助您完成婚禮中的多個不同的進程。

    不深思則不能造于道。不深思而得者,其得易失。

    名人名言- 曾國藩
    • By 優聯實達(譯)
    • 2015-10-02
    • 2291
    • 公司新聞,網站開發,網站設計,UI
  • 少妇高潮久久久久7777