# designMode
**Repository Path**: xihafugui/designMode
## Basic Information
- **Project Name**: designMode
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2018-09-28
- **Last Updated**: 2020-12-18
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# PHP设计模式
学习实践
目录
1、命名空间
2、类自动载入
3、PSR-0基础框架
4、SPL标准库
5、链式操作*
6、魔术方法的使用*
7、基础设计模式简介
8、工厂模式*
9、单例模式*
10、注册模式
11、适配器模式
12、策略模式
13、数据对象映射模式*
14、观察者模式
15、原型模式
16、装饰器模式*
17、迭代器模式*
18、代理模式
### PSR-0
1、PHP的命名空间必须与绝对路径一致
2、类名的首字母必须大写
3、除了入口文件为,其他的".php"文件必须只有一个类
### 开发符合PSR-0规范的基础框架
1、全部使用命名空间
2、所有PHP文件必须自动载入,不能有include/require
3、单一入口
### SPL库的使用(PHP 标准库)
1、SplStack、SplQueue、SplHeap、SplFixedArray等数据结构类
2、ArrayIterator、AppendIterator、Countable、ArrayObject
3、SPL提供的函数
```$xslt
/*
* 栈结构、先进后出
*/
$stack = new SplStack();
$stack->push("data1\n");//入栈
$stack->push("data2\n");//入栈
echo $stack->pop();
echo $stack->pop();
/*
* 队列结构、先进先出
*/
$queue = new SplQueue();
$queue->enqueue("data_q1");
$queue->enqueue("data_q2");
echo $queue->dequeue();
echo $queue->dequeue();
/*
* 堆结构、先进先出
*/
$heap = new SplMinHeap();//最小堆
$heap->insert("data_h1");
$heap->insert("data_h2");
echo $heap->extract();
echo $heap->extract();
/*
* 固定长度数组
*/
$heap_array = new SplFixedArray(10);
$heap_array[0] = 123;
$heap_array[9] = 321;
var_dump($heap_array);
```
### 链式操作
原理:返回 `$this`
```$xslt
class Database
{
function where($where)
{
return $this;
}
function order($order)
{
return $this;
}
function limit($limit)
{
return $this;
}
}
$db = new \Imooc\Database();
$db->where("id=1")->where("name=2")->limit("1")->order("id desc");
```
### PHP魔术方法的使用
```
1. __get/__set //接管 类的属性
2. __call/__callStatic //控制PHP对象对方法的调用
3. __toString //将对象转换成字符串
4. __invoke //将PHP对象当初函数执行
```
```$xslt
function __set($name, $value)
{
var_dump(__METHOD__);
$this->array[$name] = $value;
}
function __get($name)
{
var_dump(__METHOD__);
return $this->array[$name];
}
function __call($name, $arguments)
{
var_dump($name, $arguments);
return "magic function\n";
}
function __toString()
{
return __CLASS__;
}
function __invoke()
{
return "invoke2";
}
```
### 工厂模式
***工厂方法或者类生成对象,而不是在代码中直接new***
***好处:如果类有修改,比如修改类名,则只需要修改一处***
```$xslt
class Factory
{
static function createDatabase()
{
$db = new Database();
return $db;
}
}
$db = \Imooc\Factory::createDatabase();
```
### 单例模式
***使某个类的对象仅允许创建一个***
```$xslt
class Database
{
protected static $db;
//屏蔽构造函数,在其他地方不允许 实例化
private function __construct()
{
}
//获取实例
static function getInstance()
{
if (self::$db){
return self::$db;
}else{
self::$db = new self();
return self::$db;
}
}
}
class Factory
{
static function createDatabase()
{
$db = Database::getInstance();//此处无法 new Database(); 只能静态调用getInstance()
return $db;
}
}
$db = \Imooc\Factory::createDatabase();
```
### 注册模式
***全局共享和交换对象***
```$xslt
class Register
{
protected static $objects;
static function set($alias,$object)
{
self::$objects[$alias] = $object;
}
static function get($name)
{
return self::$objects[$name];
}
static function _unset($alias)
{
unset(self::$objects[$alias]);
}
}
class Factory
{
static function createDatabase()
{
$db = Database::getInstance();
Register::set("db1",$db);//将变量注册,赋予别名
return $db;
}
}
$db = \Imooc\Factory::createDatabase();
$db1 = \Imooc\Register::get('db1');//注册之后,直接获取别名也可以使用对象
```
### 适配器模式
***可以将 截然不同的函数接口封装成统一的API***
```$xslt
//实现统一接口
interface IDatabase
{
function connect($host, $user, $passwd, $dbname);
function query($sql);
function close();
}
//分不同场景实现接口方法
class MySQL implements IDatabase
{
protected $conn;
function connect($host, $user, $passwd, $dbname)
{
$conn = mysql_connect($host, $user, $passwd, $dbname);
mysql_select_db($dbname,$conn);
$this->conn = $conn;
}
function query($sql)
{
$res = mysql_query($sql, $this->conn);
return $res;
}
function close()
{
mysql_close($this->conn);
}
}
class MySQLi implements IDatabase
{
function connect($host, $user, $passwd, $dbname)
{
// TODO: Implement connect() method.
}
function query($sql)
{
// TODO: Implement query() method.
}
function close()
{
// TODO: Implement close() method.
}
}
class PDO implements IDatabase
{
protected $conn;
function connect($host, $user, $passwd, $dbname)
{
$this->conn = new \PDO("mysql:host=$host;dbname=$dbname", $user, $passwd);
}
function query($sql)
{
$this->conn->query($sql);
}
function close()
{
unset($this->conn);
}
}
$db = new Imooc\Database\MySQL();//此处可以替换成MySQLi()或PDO(),下面的接口方法和参数都不会变,适配器实现
$db->connect('127.0.0.1','root','','test');
$db->query();
$db->close();
```
### 策略模式
***将一组特定的行为和算法封装成类,以适应某些特定的上下文环境***
***栗子:一个电商网站系统,针对男性、女性用户要个子跳转到不同的商品类目,并且展示不同的广告***
```$xslt
//封装特定行为接口
interface UserStrategy
{
function showAd();
function showCategory();
}
//实现不同的策略
class FemaleUserStrategy implements UserStrategy
{
function showAd()
{
echo '2018女装';
}
function showCategory()
{
echo '女装';
}
}
class MaleUserStrategy implements UserStrategy
{
function showAd()
{
echo '2018新手机';
}
function showCategory()
{
echo '男装';
}
}
//使用策略模式
class Page
{
/**
* @var \Imooc\UserStrategy
*/
protected $strategy;
function index()
{
$this->strategy->showAd();
$this->strategy->showCategory();
}
function setStrategy(\Imooc\UserStrategy $strategy)
{
$this->strategy = $strategy;
}
}
$page = new Page();
//根据不同的上下文,设置不同的策略
if (isset($_GET['female'])){
$strategy = new \Imooc\FemaleUserStrategy();
}else{
$strategy = new \Imooc\MaleUserStrategy();
}
//将对象保存在成员变量
$page->setStrategy($strategy);
$page->index();
```
### 策略模式的控制反转
***使用策略模式可以实现Ioc,依赖倒置、控制反转***
### 数据对象映射模式
***将对象和数据存储映射起来,对一个对象的操作会映射为对数据存储的操作***
***复杂实现,使用数据对象映射模式、工厂模式、注册器模式***
```
class Page
{
function index()
{
$user = \Imooc\Factory::getUser(1);//工厂
$user->name = 'test1';
$this->test();
}
function test()
{
$user = \Imooc\Factory::getUser(1);//工厂
$user->mobile = '18900001111';
}
}
$page = new Page();
$page->index();
class Factory
{
/**
* @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;
}
}
//数据对象映射
class User
{
public $id;
public $name;
public $mobile;
public $regtime;
protected $db;
function __construct($id)
{
$this->db = new MySQLi();//此处可以替换成MySQLi()或PDO(),下面的接口方法和参数都不会变,适配器实现
$this->db->connect('127.0.0.1','root','','test');
$res = $this->db->query('select * from user limit 1');
$data = $res->fetch_assoc();
}
function __destruct()
{
$this->db->close();
}
}
```
### 观察者模式
***当一个对象状态发生改变时,依赖它的对象全部会收到通知,并自动更新***
***低耦合,非侵入式的通知与更新机制***
```
/**
* 事件产生者
* Class EventGenerator
* @package Imooc
*/
abstract class EventGenerator
{
private $observers = [];
function addObserver(Observer $observer)
{
$this->observers[] = $observer;
}
function notify()
{
foreach ($this->observers as $observer){
$observer->update();
}
}
}
/**
* 事件观察者接口
* Interface Observer
* @package Imooc
*/
interface Observer
{
function update($event_info = null);
}
/**
* 使用观察者模式
*/
class Event extends \Imooc\EventGenerator
{
function trigger()
{
echo "Event
\n";
$this->notify();
}
}
class Observer1 implements \Imooc\Observer
{
function update($event_info = null)
{
echo "逻辑1
\n";
}
}
class Observer2 implements \Imooc\Observer
{
function update($event_info = null)
{
echo "逻辑2
\n";
}
}
$event = new Event();
$event->addObserver(new Observer1());//添加观察者
$event->addObserver(new Observer2());//添加观察者
$event->trigger();
```
### 原型模式
***与工厂模式作用类似,都是用来创建对象***
***与工厂模式的实现不同,原型模式是先创建好一个原型对象,然后通过clone原型对象类创建新的对象。这样就免去了类创建时重复的初始化操作***
***原型模式适用于大对象的创建。没创建一个大对象需要很大的开销,如果每次new就会消耗很大,原型模式仅需内存拷贝即可***
```
//大对象
class Canvas
{
public $data;
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 draw()
{
foreach($this->data as $line)
{
foreach($line as $char)
{
echo $char;
}
echo "
\n";
}
}
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] = ' ';
}
}
}
}
//实现原型模式
$prototype = new \Imooc\Canvas();//创建原型对象
$prototype->init();//利用原型对象进行初始化操作
$canvas1 = clone $prototype;//克隆原型对象
$canvas1->rect(3,6,4,12);
$canvas1->draw();
echo '=============================
';
$canvas2 = clone $prototype;//克隆原型对象
$canvas2->rect(1,3,2,6);
$canvas2->draw();
```
### 装饰器模式
***装饰器模式(Decorator),可以动态添加修改类的功能***
***一个类提供了一项功能,如果要在修改并添加额外的功能,传统的编程模式,需要写一个子类继承它,并重新实现类的方法***
***使用装饰器模式,仅需在运行时添加一个装饰器对象即可实现,可以实现最大的灵活性***
```
interface DrawDecorator
{
function beforeDraw();
function afterDraw();
}
class Canvas
{
public $data;
protected $decorators = array();
//Decorator
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);//after 后进先出
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 ColorDrawDecorator implements DrawDecorator
{
protected $color;
function __construct($color = 'red')
{
$this->color = $color;
}
function beforeDraw()
{
echo "