问题
你如何能轻松方便地建立这么" 复杂 " 的对象即操作中不需要粘贴复制呢?
解决方法
建立一个工厂(一个函数或一个类方法)来制造新的对象。
我们来看一个实际的例子:书店上架N种图书,图书有价格、名称和作者三种属性,用户购买图书时会有不同的等级,比如:普通用户、VIP用户、内部员工,每一种等级对象不同的折扣。现在要求根据用户的不同等级和购书的数量计算用户应付金额。
我们来看用工厂模式编写的代码:
user.php:
<?php
interface User {
public function getName();
public function setName($_name);
public function getDiscount();
}
abstract class AbstractUser implements User {
private $name = "";
protected $discount = 0;
protected $grade = "";
public function __construct($_name) {
$this->setName($_name);
}
public function getName() {
return $this->name;
}
public function setName($_name) {
$this->name = $_name;
}
public function getDiscount() {
return $this->discount;
}
public function getGrade() {
return $this->grade;
}
}
class NormalUser extends AbstractUser {
protected $discount = 1.0;
protected $grade = "NormalUser";
}
class VipUser extends AbstractUser {
protected $discount = 0.8;
protected $grade = "VipUser";
}
class InnerUser extends AbstractUser {
protected $discount = 0.7;
protected $grade = "InnerUser";
}
userFactory.php:
<?php
require_once("user.php");
abstract class UserFactory {
static function createUser($_grade, $_name) {
if ("NormalUser" == $_grade) {
return new NormalUser($_name);
} elseif ("VipUser" == $_grade) {
return new VipUser($_name);
} elseif ("InnerUser" == $_grade) {
return new InnerUser($_name);
} else {
echo "some exception";
return null;
}
}
}
product.php:
<?php
interface Product {
public function getProductName();
public function getProductPrice();
}
interface Book extends Product {
public function getAuthor();
}
class BookOnline implements Book {
private $productName;
private $productPrice;
private $author;
public function __construct($_bookName) {
$this->productName = $_bookName;
}
public function getProductName() {
return $this->productName;
}
public function getProductPrice() {
$this->productPrice = 100;
return $this->productPrice;
}
public function getAuthor() {
return $this->author;
}
}
productFactory.php:
<?phprequire_once("product.php");
abstract class ProductFactory {
public static function createProduct($_type, $_name) {
if ("book" == $_type) {
return new BookOnline($_name);
} else {
return null;
}
}
}
productSettle.php:
<?php
include_once("user.php");
include_once("product.php");
class ProductSettle {
public static function finalPrice(User $_user,Product $_product,$number =1) {
$price = $_user->getDiscount() * $_product->getProductPrice() * $number;
return $price;
}
public static function getInfo(User $user,$product,$number) {
if ($user != null & $product != null ) {
$price = ProductSettle::finalPrice($user,$product,$number);
$str = "您好,尊敬的用户" . $user->getName() . "<br />";
$str .= "您的级别是 " . $user->getGrade() . "<br />";
$str .= "您的折扣是" . $user->getDiscount() . "<br />";
$str .= "够买 $number 本 《" .$product->getProductName();
$str .= ">>的价格是 $price <br /><br />";
return $str;
} elseif (null==$user) {
return "用户不存在";
} else {
return "产品不存在";
}
}
}
test_45.php:
<?php
header("Content-type:text/html;charset=utf-8");
include_once("userFactory.php");
include_once("productFactory.php");
include_once("productSettle.php");
$number = 10;
$bookName = "设计模式";
$book = ProductFactory::createProduct("book", $bookName);
$normalUser = UserFactory::createUser("NormalUser", "Tom");
$vipUser = UserFactory::createUser("VipUser", "Jack");
$innerUser = UserFactory::createUser("InnerUser", "Jerry");
echo ProductSettle::getInfo($normalUser, $book, $number);
echo ProductSettle::getInfo($vipUser, $book, $number);
echo ProductSettle::getInfo($innerUser, $book, $number);
在test_45.php中,我们看到由于类的职责非常明了,相应的方法也已经封装好,因此php语句写起来非常简单并且清晰易懂。