1.工厂模式(Factory)
<?php
namespace DesignPattern;
class Factory
{
static function createDatabase()
{
$db = new Database();
return $db;
}
}
2.单例模式
<?php
namespace DesignPattern;
class Database
{
static protected $db;
private function __construct()
{
}
static function getInstance()
{
if(self::$db)
{
return self::$db;
}else{
self::$db = new self();
return self::$db;
}
}
}
3.注册模式(Register)
<?php
namespace DesignPattern;
class Register
{
protected static $objects;
static function set($alias, $object)
{
self::$objects[$alias] = $object;
}
static function get($alias)
{
return self::$objects[$alias];
}
static function _unset($alias)
{
unset(self::$objects[$alias]);
}
}
4.适配器模式 (Adapter)
- 将截然不同的函数接口封装成统一的API
- 示例,PHP的数据库驱动有mysql,mysqli,pdo等。cache适配器:memcached,redis,file,apc统一成一致的API
// thinkphp/library/think/cache
// thinkphp/library/think/log
5.策略模式(Strategy)
- 将一组特定的行为和算法封装成类,以适应某些特定的上下文环境
- 示例:电商网站系统,针对男性女性用户各自跳转不同的商品目录,并且所有广告位展示不同的广告
- 使用策略模式可以实现Ioc,依赖倒置、控制反转
// UserStrategy.php
<?php
namespace DesignPattern;
interface UserStrategy
{
function showAd();
function showCategory();
}
// FemaleUserStrategy.php
<?php
namespace DesignPattern;
class FemaleUserStrategy implements UserStrategy
{
function showAd()
{
echo '2014新款女装';
}
function showCategory()
{
echo '女装';
}
}
// MaleUserStrategy.php
<?php
namespace DesignPattern;
class MaleUserStrategy implements UserStrategy
{
function showAd()
{
echo 'Iphone6';
}
function showCategory()
{
echo '电子产品';
}
}
// index.php
class Page
{
/**
* @var DesignPattern\UserStrategy
*/
protected $strategy;
function index()
{
$this->strategy->showAd();
echo "<br>";
$this->strategy->showCategory();
}
function setStrategy(DesignPattern\UserStrategy $strategy)
{
$this->strategy = $strategy;
}
}
$page = new Page();
if(isset($_GET['female']))
{
$strategy = new DesignPattern\FemaleUserStrategy();
}else{
$strategy = new DesignPattern\MaleUserStrategy();
}
$page->setStrategy($strategy);
$page->index();
6.数据对象映射模式
7.观察者模式(Observer)
- 当一个对象状态发生改变时,依赖它的对象全部会收到通知,并自动更新
- 场景:一个事件发生后,要执行一连串更新操作。传统的编程方式,就是在事件的代码之后直接加入处理逻辑。当更新的逻辑增多之后,代码会变得难以维护。这种方式是耦合的,侵入式的,增加新的逻辑需要修改事件主体的代码
- 观察者模式实现了低耦合,非侵入式的通知和更新机制
// Observer.php
<?php
namespace DesignPattern;
interface Observer
{
function update($event_info = null);
}
// EventGenerator.php
<?php
namespace DesignPattern;
abstract class EventGenerator
{
private $observers = array();
function addObserver(Observer $observer) {
$this->observers[] = $observer;
}
function notify() {
foreach ($this->observers as $observer) {
$observer->update();
}
}
}
// index.php
class Event extends \DesignPattern\EventGenerator
{
function trigger()
{
echo "Event<br>\n";
$this->notify();
//update
// echo "逻辑1<br>\n";
// echo "逻辑2<br>\n";
// echo "逻辑3<br>\n";
}
}
class Observer1 implements \DesignPattern\Observer
{
function update($event_info = null)
{
echo "逻辑1<br>\n";
}
}
class Observer2 implements \DesignPattern\Observer
{
function update($event_info = null)
{
echo "逻辑2<br>\n";
}
}
$event = new Event();
$event->addObserver(new Observer1());
$event->addObserver(new Observer2());
$event->trigger();
8.原型模式(Prototype)
- 与工厂模式作用类似,都是用来创建对象的
- 与工厂模式的实现不同,原型模式是先创建好一个原型对象,然后通过clone原型对象来创建新的对象。这样就免去了类创建时重复的初始化操作
- 原型模式适用于大对象的创建。创建一个大对象需要很大的开销,如果每次new就会消耗很大,原型模式仅需要内存拷贝即可
$prototype = new \DesignPattern\Canvas();
$prototype->init();
$canvas1 = clone $prototype;
$canvas1->rect(3, 6, 4, 12);
$canvas1->draw();
echo "============================<br>\n";
$canvas2 = clone $prototype;
$canvas2->rect(1, 3, 2, 6);
$canvas2->draw();
9.装饰器模式 (Decorator)
- 可以动态添加修改类的功能
- 一个类提供了一项功能,如果要在修改并添加额外的功能,传统的编程模式,需要写一个子类继承它,并重新实现类的方法
- 使用装饰器模式,仅需在运行时添加一个装饰器对象即可实现,可以实现最大的灵活性
// DrawDecorator.php
<?php
namespace DesignPattern;
interface DrawDecorator
{
function beforeDraw();
function afterDraw();
}
// ColorDecorator.php
<?php
namespace DesignPattern;
class ColorDecorator implements DrawDecorator
{
protected $color;
function __construct($color = 'red')
{
$this->color = $color;
}
function beforeDraw()
{
echo "<div style='color: {$this->color}'>";
}
function afterDraw()
{
echo "</div>";
}
}
// Canvas.php
<?php
namespace DesignPattern;
class Canvas
{
public $data;
protected $decorators = array();
function init($width = 20, $height = 10) {
$data = array();
for ($i = 0; $i < $height; $i++) {
for ($j = 0; $j < $width; $j++) {
$data[$i][$j] = '+';
}
}
$this->data = $data;
}
// 接口作为引用类型来使用,任何实现该接口的类的实例都可以存储在该接口类型的变量中,通过这些变量可以访问类中所实现的接口中的方法
function addDecorator(DrawDecorator $decorator) {
$this->decorators[] = $decorator;
}
function beforeDraw()
{
foreach ($this->decorators as $decorator) {
$decorator->beforeDraw();
}
}
function afterDraw()
{
$decorators = array_reverse($this->decorators);
foreach ($decorators as $decorator) {
$decorator->afterDraw();
}
}
function draw()
{
$this->beforeDraw();
foreach ($this->data as $line) {
foreach ($line as $char) {
echo $char;
}
echo "<br>\n";
}
$this->afterDraw();
}
function rect($a1, $a2, $b1, $b2) {
foreach ($this->data as $k1 => $line) {
if($k1 < $a1 or $k1 > $a2) continue;
foreach ($line as $k2 => $char) {
if($k2 < $b1 or $k2 > $b2) continue;
$this->data[$k1][$k2] = '=';
}
}
}
}
//index.php
$prototype = new \DesignPattern\Canvas();
$prototype->init();
$canvas1 = clone $prototype;
// 接口作为引用类型来使用,任何实现该接口的类的实例都可以存储在该接口类型的变量中,通过这些变量可以访问类中所实现的接口中的方法
$canvas1->addDecorator(new \DesignPattern\ColorDecorator('green'));
$canvas1->rect(3, 6, 4, 12);
$canvas1->draw();
10.迭代器模式 (Iterator) SPL
- 在不需要了解内部实现的前提下,遍历一个聚合对象的内部元素
- 相比于传统的编程模式,迭代器模式可以隐藏遍历元素的所需的操作
11.代理模式(Proxy)
- 在客户端与实体之间建立一个代理对象,客户端对实体进行操作全部委派给代理对象,隐藏实体的具体实现细节。
- Proxy还可以与业务代码分离,部署到另外的服务器。业务代码中通过RPC来委派任务。