设计模式:外观设计模式 (一)


这个系列为 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
  • 2527
  • 公司新闻,网站开发,网站设计,UI