代理模式
想买一部国内还未上架, 自己却买不到的最新款的顶配 Mac Book Pro ... 该怎么办 ?

MacBook Pro
简单的方式为我们假借找他人 ( 能买到的人 ) 之手,帮我们购买 ... 代理模式很好理解,用一个类来代表另一个类的功能,以便向外界提供功能接口。生活中也处处能体现“代理模式”,黄牛代为买票,代购代为买海外产品 ... 很显然的一个优势是真实对象通过代理对象来满足自身的无尽欲望,而不被外界所知真实对象的真实面貌 ... 当然,过程就变得繁复麻烦了些 ...

假借他人之手
代理模式的关键点是代理对象与目标对象,代理对象是对目标对象的扩展,且会调用目标对象,常见的代理有远程代理、虚拟代理、保护代理、智能引用。
// 主体
namespace Mode\Proxy;
interface Subject {
public function buyMBP();
}
// 真实对象
namespace Mode\Proxy;
class RealSubject implements Subject {
public function buyMBP() {
// TODO: Implement buyMBP() method.
echo "买了一部国内还未上架的顶配 Mac Book Pro";
}
}
// 代理
namespace Mode\Proxy;
class Proxy implements Subject {
public function buyMBP() {
// TODO: Implement buyMBP() method.
$realSubject = new RealSubject();
$realSubject->buyMBP();
}
}
// 调用
require '../autoload.php';
use Mode\Proxy\Proxy;
$proxy = new Proxy();
$proxy->buyMBP();
工厂模式
再回到“简单工厂模式”两数的和运算实现上(具体可看如下提供链接内容),如果新增一种运算,就要修改 OperationFactory 抽象类增加 switch case 分支进行判断,但是这样操作违背了 OCP 的原则。
《大话设计模式》- 简单工厂模式
《大话设计模式》- 开放封闭与里氏代换

工厂
“工厂方法模式”就是将具体的创建过程交给子类工厂去实现,让类的实例化推迟到子类去进行。是对“简单工厂模式”的进一步抽象。比如上述新增运算符时,只需创建一个具体的运算符工厂类就可以获取新的实例,而无需改动 OperationFactory 工厂,使其更加符合 OCP 原则。虽然更加符合 OCP 原则了,但每增加一种运算方式就需要加一个工厂的类,增加了额外的开发量,虽然“工厂方法模式”将原本改动工厂类的操作省了,但还是需要修改客户端调用的代码,有没有办法做到更优 ? 反射 ...
// 工厂接口
namespace Mode\Factory\Method;
interface OperationFactory {
public function createOperation();
}
// 具体工厂子类 - 加法
namespace Mode\Factory\Method;
class OperationAddFactory implements OperationFactory {
public function createOperation() {
// TODO: Implement createOperation() method.
return new OperationAdd();
}
}
// 具体工厂子类 - 减法
namespace Mode\Factory\Method;
class OperationSubFactory implements OperationFactory {
public function createOperation() {
// TODO: Implement createOperation() method.
return new OperationSub();
}
}
// 操作抽象类
namespace Mode\Factory\Method;
abstract class Operation {
protected $numA = 0;
protected $numB = 0;
abstract public function getResult();
public function setNumbers($numA = 0, $numB = 0) {
$this->numA = $numA;
$this->numB = $numB;
}
}
// 具体操作类 - 加法
namespace Mode\Factory\Method;
class OperationAdd extends Operation {
public function getResult() {
// TODO: Implement getResult() method.
return $this->numA + $this->numB;
}
}
// 具体操作类 - 减法
namespace Mode\Factory\Method;
class OperationSub extends Operation {
public function getResult() {
// TODO: Implement getResult() method.
return $this->numA - $this->numB;
}
}
// 调用
require '../../autoload.php';
use Mode\Factory\Method\OperationAddFactory;
$numA = 20;
$numB = 10;
$facotry = new OperationAddFactory();
$operator = $facotry->createOperation();
$operator->setNumbers($numA, $numB);
echo $numA.'+'.$numB.'='.$operator->getResult();