DesignPattern_PHP
PHP 基础设计模式学习,默认自动加载类
单例模式
一个类只允许实例化一次:如数据库类
<?php
class Database
{
private $instance;
private function __construct(){}
public static function getInstance()
{
if(empty(self::$instance)) {
self::$instance = new self();
}
return self::$instance;
}
private function __clone(){}
}
工厂模式
对一个类实现统一实例化
一个类如果在多个地方实例化
可以实现统一修改
<?php
class Factory
{
public static function createDatabase()
{
$obj = new Database(); //Database::getInstance();
return $obj;
}
}
注册器模式
单例模式保证了一个类中只有一个实例被全局访问,当你有一组全局对象被全局访问时可能就需要用到**注册模式 **
<?php
class Register
{
private static $objects;
public static function set($alias, $object)
{
self::$objects[$alias] = $object;
}
public static function get($alias)
{
if(!isset($objects[$alias])) {
return null;
}
return $objects[$alias];
}
public static function remove($alias)
{
unset($objects[$alias]);
}
}
Ico 容器
<?php
class Container
{
protected $binds;
protected $instances;
// 绑定注册脚本
public function bind($abstract, $concrete)
{
if ($concrete instanceof Closure) {
$this->binds[$abstract] = $concrete;
} else {
$this->instances[$abstract] = $concrete;
}
}
// 运行注册脚本
public function make($abstract, $parameters = [])
{
if (isset($this->instances[$abstract])) {
return $this->instances[$abstract];
}
$parameters = (array) $parameters;
array_unshift($parameters, $this);
return call_user_func_array($this->binds[$abstract], $parameters);
}
}
$container = new Container();
$container->bind('databases', function ($container) {
return new PDO();
});
$db = $container->make('databases');
适配器模式
可以将不同的接口封装成统一的API,如:mysql,mysqli,pdo
<?php
instance Database
{
public function construct(Array $config);
public function query($sql);
public function close();
}
class Mysqli implements Database
{
public function construct($cofig)
{
extract($config);
$this->conn = mysqli_connect($host, $user, $passwd, $dbname);
}
public function query($sql)
{
// ...
}
public function close()
{
// ...
}
}
class PDO implements PDO
{
public function construct($config)
{
extract($config);
$this->conn = new \PDO("mysql:host=$host;dbname=$dbname", $user, $passwd);
}
public function query($sql)
{
// ...
}
public function close()
{
// ...
}
}
策略模式
将一组特定的行为或算法封装成类,以适应某些上下文环境
<?php
interface Strategy
{
public function title();
public function content();
}
class PostNoe implements Strategy
{
public function title()
{
echo '文章1的标题';
}
public function content()
{
echo '文章1的内容';
}
}
class PostTwo implements Strategy
{
public function title()
{
echo '文章2的标题';
}
public function content()
{
echo '文章2的内容';
}
}
class Post
{
private $strategy;
public function show()
{
$this->strategy->title();
$this->strategy->content();
}
public function setStrategy(Strategy $strategy)
{
$this->strategy = $strategy;
}
}
$post = new Post();
$post->setStrategy(new PostTwo);
$post->show();
数据映射
<?php
class User
{
protected $attributes;
protected $db;
protected $table = 'users';
public function __construct()
{
$this->db = new PDO("mysql:host=192.168.10.10;dbname=zhihu", 'homestead', 'secret');
$res = $this->db->query("select * from users limit 1");
$this->attributes = $res->fetch(PDO::FETCH_ASSOC);
}
function __destruct()
{
// TODO: Implement __destruct() method.
}
function __get($key)
{
return $this->attributes[$key];
}
function __set($key, $value)
{
$this->attributes[$key] = $value;
}
function save()
{
$sql = "update {$this->table} set ";
foreach ($this->attributes as $key => $attribute) {
$sql .= "`{$key}`='{$attribute}',";
}
$sql = trim($sql, ',');
$sql .= ' where id=1';
$this->db->query($sql);
}
观察者模式
当一个对象状态发生改变时,依赖他的对象全部会收到通知,并自动更新
<?php
# 观察者,当事件发生者(事件触发),观察者自动更新 update
class Logic1 implements SplObserver
{
public function update(SplSubject $subject)
{
echo 'Logic1\n';
}
}
class Logic2 implements SplObserver
{
public function update(SplSubject $subject)
{
echo 'Logic2\n';
}
}
# 事件发生者
abstract Event implements SplSubject
{
// 观察者对象集合
private $observers;
// 添加观察者
public function attach(SplObserver $observer)
{
$this->observers[] = $observer;
}
public function detach(SplObserver $observer)
{
if($index = array_search($observer, $this->observers)) {
unset($this->observers[$index]);
}
}
// 通知
public function notify()
{
// 遍历观察者对象,逐一执行 观察者 update
foreach($this->observers as $observer) {
$observer->update($this);
}
}
}
class EventTrigger extends Event
{
// 事件发生
public function trigger()
{
echo 'event trigger';
// 通知
$this->notify();
}
}
装饰器
扩展一个类一般可以使用继承或者组合的形式。使用继承的方式扩展时,随着基类子类的增多,以及子类的子类出现,继而出现了代码的无限制膨胀,增加了系统的复杂性。而使用装饰者模式既继承又引用,能动态扩展类的一些功能,减少了继承数量。
<?php
#代码实例(出自php设计模式)
interface Component
{
public function operation();
}
/**
* 装饰角色
*/
class Decorator implements Component
{
protected $component;
public function __construct(Component $component)
{
$this->component = $component;
}
public function operation()
{
$this->component->operation();
}
}
/**
* 具体装饰类A
*/
class ConcreteDecoratorA extends Decorator
{
public function __construct(Component $component)
{
parent::__construct($component);
}
public function operation()
{
parent::operation();
$this->addedOperationA();//新添加的操作
}
public function addedOperationA()
{
echo 'Add Operation A <br />';
}
}
/**
* 具体装饰类B
*/
class ConcreteDecoratorB extends Decorator
{
public function __construct(Component $component)
{
parent::__construct($component);
}
public function operation()
{
parent::operation();
$this->addedOperationB();//新添加的操作
}
public function addedOperationB()
{
echo 'Add Operation B <br />';
}
}
/**
* 具体构件
*/
class ConcreteComponent implements Component
{
public function operation()
{
echo 'Concrete Component operation <br />';
}
}
/**
* 客户端
*/
class Client
{
public static function main()
{
$component = new ConcreteComponent();
$decoratorA = new ConcreteDecoratorA($component);
$decoratorB = new ConcreteDecoratorB($decoratorA);
$decoratorA->operation();
$decoratorB->operation();
}
}
Client::main();
// 输出
// Concrete Component operation <br />
// Add Operation A <br />
//
// Concrete Component operation <br />
// Add Operation A <br />
// Add Operation B <br />
迭代器
迭代器模式提供一种访问一个容器对象中的各个元素,而又不暴露其内部细节的方法。
<?php
class TestIterator implements Iterator
{
private $data;
private $index;
private $count;
public function __construct($data)
{
$this->data = $data;
$this->index = 0;
$this->count = count($this->data);
}
public function rewind()
{
echo __METHOD__;
$this->index = 0;
}
public function valid()
{
echo __METHOD__;
return $this->index < $this->count;
}
public function key()
{
echo __METHOD__;
return $this->index;
}
public function current()
{
echo __METHOD__;
$row = $this->data[$this->index];
$row['ip'] = gethostbyname($row['url']);
return $row;
}
public function next() {
echo __METHOD__;
$this->index ++;
}
}
$array = array(
array('url' => 'www.zeroplace.cn'),
array('url' => 'www.baidu.com'),
);
$d = new TestIterator($array);
foreach($d as $k => $v) {
echo '---------------';
echo $v['url'] . '===' . $v['ip'];
echo '###############';
}
// TestIterator::rewind
// TestIterator::valid
// TestIterator::current
// TestIterator::key
// ---------------
// www.zeroplace.cn
// ###############
// TestIterator::next
// TestIterator::valid
// TestIterator::current
// TestIterator::key
// ---------------
// www.baidu.com
// ###############
// TestIterator::next
// TestIterator::valid