注册器(树)模式:用来将对象注册到全局的树上面,在哪里都能访问
namespace DuiCode;
class Register{
protected $objects;
//将类映射注册到全局树上
/**
* @param $alias 别名
* @param $object 对象
*/
static function set($alias, $object){
self::$objects[$alias] = $object;
}
//获取注册的对象
static function get($name){
return self::$objects[$name];
}
function _unset($alias){
unset(self::$objects[$alias]);
}
}
工厂模式
namespace DuiCode;
use DuiCode\Database\MySQLi;
class Factory{
static function createDatabase(){
$db = Database::getInstance();
return $db;
}
static $proxy = null;
/**
* @param $id
* @return User
*/
static function getUser($id)
{
$key = 'user_'.$id;
$user = Register::get($key);
if (!$user) {
$user = new User($id);
Register::set($key, $user);
}
return $user;
}
/**
* @param $name
* @return bool
*/
static function getModel($name)
{
$key = 'app_model_'.$name;
$model = Register::get($key);
if (!$model) {
$class = '\\App\\Model\\'.ucwords($name);
$model = new $class;
Register::set($key, $model);
}
return $model;
}
static function getDatabase($id = 'proxy')
{
if ($id == 'proxy')
{
if (!self::$proxy)
{
self::$proxy = new \DuiCode\Database\Proxy;
}
return self::$proxy;
}
$key = 'database_'.$id;
if ($id == 'slave')
{
$slaves = Application::getInstance()->config['database']['slave'];
$db_conf = $slaves[array_rand($slaves)];
}
else
{
$db_conf = Application::getInstance()->config['database'][$id];
}
$db = Register::get($key);
if (!$db) {
$db = new Database\MySQLi();
$db->connect($db_conf['host'], $db_conf['user'], $db_conf['password'], $db_conf['dbname']);
Register::set($key, $db);
}
return $db;
}
}
适配器模式:将截然不同的函数接口封装成统一的API
举例:mysql,mysqli,pdo三种数据库操作可以用适配器模式统一成一致,还有将 memcache、redis、file、apc等不同的缓存函数,统一成一致
interface IDatabase{
function connect($host, $user, $passwd, $dbname);
function query($sql);
function close();
}
//PHP中链式操作的实现
class Database{
protected $db;
/**!!!!!单例模式!!!!!!!**/
//构造方法私有化
private function __construct(){
}
//获取实例
static function getInstance(){
if (self::$db){
return self::$db;
}else {
self::$db = new self();
return self::$db;
}
}
function where($where){
//这一句就是为了实现链式操作
return $this;
}
function order($order){
return $this;
}
function limit($limit){
return $this;
}
}
class MySQL implements IDatabase{
protected $conn;
function connect($host, $user, $passwd, $dbname){
// TODO: Implement connect() method.
$conn = mysql_connect($host, $user, $passwd);
mysql_select_db($dbname,$conn);
$this->conn = $conn;
}
function query($sql){
// TODO: Implement query() method.
$res = mysql_query($sql,$this->conn);
return $res;
}
function close(){
// TODO: Implement close() method.
mysql_close($this->conn);
}
}
策略模式:将一组特定的行为和算法封装成类,以适应某些特定的上下文环境,这种模式就是策略模式,
比如一个电商网站,针对男女用户要各自跳转到不同的商品类目,并且所有广告位展示不同广告。
namespace DuiCode;
interface UserStrategy{
function showAd();
function showCategory();
}
namespace DuiCode;
class FemaleUserStrategy implements UserStrategy{
function showAd(){
// TODO: Implement showAd() method.
echo "新款女装";
}
function showCategory(){
// TODO: Implement showCategory() method.
echo "女装";
}
}
class Page{
protected $strategy;
function index(){
echo "AD:";
$this->strategy->showAd();
echo "
";
echo "Category:";
$this->strategy->showCategory();
echo "
";
}
function setStrategy(\DuiCode\UserStrategy $strategy){
$this->strategy = $strategy;
}
}
$page = new Page;
if (isset($_GET['female'])){
$strategy = new \DuiCode\FemaleUserStrategy();
}else{
$strategy = new \DuiCode\MaleUserStrategy();
}
$page->setStrategy($strategy);
数据对象映射模式,是将对象和数据存储映射起来,对一个对象的操作会映射为对数据存储的操作,比如ORM类,将复杂的SQL语句映射成对象属性的操作。
namespace DuiCode;
class User{
public $id;
public $name;
public $mobile;
public $regtime;
protected $db;
function __construct($id){
$this->db = new \DuiCode\Database\MySQLi();
$this->db->connect('127.0.01','root','root','test');
$res = $this->db->query("SELECT * FROM user LIMIT 1;");
$data = $res->fetch_assoc();
$this->id = $data['id'];
$this->name=$data['name'];
$this->mobile=$data['mobile'];
$this->regtime=$data['regtime'];
}
function __destruct(){
// TODO: Implement __destruct() method.
$this->db->query("UPDATE user SET name = '{$this->name}',mobile='{$this->mobile}',regtime='{$this->regtime}' WHERE id = {$this->id} LIMIT 1;");
}
}
观察者模式:当一个对象状态发生改变时,依赖它的对象全部会受到通知,并自动更新。观察者模式实现了低耦合,非侵入式的通知与更新机制。
namespace DuiCode;
interface Observer{
function update($event_info = null);
}
namespace DuiCode;
abstract class EventGenerator{
private $observers = array();
function addObserver(Observer $observer){
$this->observers[] = $observer;
}
function notify(){
foreach ($this->observers as $observer){
$observer->update();
}
}
}
class Event extends \DuiCode\EventGenerator{
function trigger(){
echo "Event
\n";
/**传统模式update
echo "逻辑1
\n";
echo "逻辑2
\n";
echo "逻辑3
\n";
**/
//发送通知
$this->notify();
}
}
原型模式:与工厂模式类似,都是用来创建对象,与工厂模式的实现不同,原型模式是先创建好一个原型对象,然后通过clone原型对象来创建新的对象。这样就免去了类创建时重复的初始化操作。原型模式适用于大对象的创建,创建一个大对象需要很大的开销,如果每次new就会消耗很大,原型模式仅需内存拷贝即可。
//原型模式
$prototype = new \DuiCode\Canvas();
$prototype->init();
$canvas3 = clone $prototype;
$canvas3->init();
$canvas3->rect(3, 6, 4, 12);
$canvas3->draw();
echo '
\n';
$canvas4 = clone $prototype;
$canvas4->init();
$canvas4->rect(1, 3, 2, 6);
$canvas4->draw();
装饰器模式:可以动态地添加修改类的功能。一个类提供了一项功能,如果在修改并添加额外的功能,传统的编程模式,需要写一个子类继承它,并重新实现类的方法。使用装饰器模式,仅需在运行时添加一个装饰器对象,即可实现,可以实现最大的灵活性。
namespace DuiCode;
interface DrawDecorator{
function beforeDraw();
function afterDraw();
}
namespace DuiCode;
class ColorDrawDecorator implements DrawDecorator{
protected $color;
function __construct($color = 'red'){
$this->color = $color;
}
function beforeDraw(){
// TODO: Implement beforeDraw() method.
echo "";
}
function afterDraw(){
// TODO: Implement afterDraw() method.
echo "";
}
}
namespace DuiCode;
class SizeDrawDecorator implements DrawDecorator{
protected $size;
function __construct($size = '14px'){
$this->size = $size;
}
function beforeDraw(){
// TODO: Implement beforeDraw() method.
echo "";
}
function afterDraw(){
// TODO: Implement afterDraw() method.
echo "";
}
}
namespace DuiCode;
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 "
\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] = ' ';
}
}
}
}
迭代器模式:在不需要了解内部实现的前提下,遍历一个聚合对象的内部元素。相对于传统的编程模式,迭代器模式可以隐藏遍历元素所需的操作。
class AllUser implements \Iterator{
protected $ids;
protected $data = array();
protected $index;
function __construct(){
$db = Factory::getDatabase();
$result = $db->query("SELECT id FROM user");
$this->ids = $result->fetch_all(MYSQLI_ASSOC);
}
//获取当前的元素(第三个调用)
function current(){
// TODO: Implement current() method.
$id = $this->ids[$this->index]['id'];
return Factory::getUser($id);
}
//下一个元素(第四步)
function next(){
// TODO: Implement next() method.
$this->index ++;
}
//验证当前是否还有下一个元素(第二个调用)
function valid(){
// TODO: Implement valid() method.
return $this->index < count($this->ids);
}
//重置整个迭代器
function rewind(){
// TODO: Implement rewind() method.
return $this->index;
}
//在迭代器中的位置(第一个调用)
function key(){
// TODO: Implement key() method.
$this->index = 0;
}
}
代理模式:在客户端与实体之间建立一个代理对象(proxy),客户端对实体进行操作全部委派给代理对象,隐藏实体的具体实现细节。Proxy还可以与业务代码分离,部署到另外的服务器,业务代码通过RPC来委派任务。
namespace DuiCode;
interface IUserProxy{
function getUserName($id);
function setUserName($id, $name);
}
namespace DuiCode;
class Proxy implements IUserProxy{
function getUserName($id){
// TODO: Implement getUserName() method.
//这里写数据库操作
}
function setUserName($id, $name){
// TODO: Implement setUserName() method.
//这里写数据库操作
}
}
下面介绍一下PHP中封装好的一些数据结构
//SPL常用数据结构的使用
//栈 先进后出
$stack = new SplStack();
$stack->push("打他"); //入栈
$stack->pop(); //出栈
//队列 先进先出
$queue = new SplQueue();
$queue->enqueue("揍他"); //入队列
$queue->dequeue(); //出队列
//堆
//最小堆
$heap = new SplMinHeap();
$heap->insert("夯他"); //插入
$heap->extract(); //提取
//固定长度的数组
$array = new SplFixedArray(10);
$array[0] = 123;
$array[9] = 1234;
PHP魔术方法大致分成四类:
1、__set/__get,修改对象不存在的属性和获取对象不存在的属性;
2、__toString();将一个对象当成一个字符串打印的时候调用;
3、__call/__callStatic:调用一个不存在的方法或者一个不存在的静态方法的时候调用;
4、__invoke,将对象当成函数调用的时候该魔术方法被调
面向对象的基本原则:
1.单一职责:一个类,只需要做好一件事情。
2.开放封闭:一个类应该是可扩展的,而不可修改的。
3.依赖倒置:一个类,不应该强依赖另外一个类。每个类对于另外一个类都是可替代的。
4.配置化:尽可能地使用配置,而不是硬编码。
5.面向接口编程:只需要关心接口,不需要关心实现。
配置与设计模式
1.PHP中使用ArrayAccess实现配置文件的加载
2.在工厂方法中读取配置,生成可配置化得对象
3.使用装饰器模式实现权限验证,模板渲染,JSON串化
4.使用观察者模式实现数据更新事件的一系列更新操作
5.使用代理模式实现数据库的主从自动切换
更多源码请查LearningPHP