PHP设计模式
一.工厂模式
定义:
工厂模式(Factory Pattern),就是负责生成其他对象的类或方法,也叫工厂方法模式
抽象工厂模式( Abstract Factory Pattern),可简单理解为工厂模式的升级版
本质意义:
统一管理多种类的实例化,有利于代码可维护性
实例:
例1.
//工厂类
class Factor{
//生成对象方法
static function createDB(){
echo '我生产了一个DB实例';
return new DB;
}
}
//数据类
class DB{
public function construct(){
echo CLASS__.PHP_EOL;
}
}
$db=Factor::createDB();
页面输出:
我生产了一个DB实例DB
二.单例模式
定义:
单例模式(Singleton Pattern):顾名思义,就是只有一个实例。作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
本质意义:为复用比较经常的类,提供唯一实例对象,节约资源。比如数据库类的调用。
代码通用概括:三私一公。(1私有化一个属性用于存放唯一的一个实例。2私有化构造方法,私有化克隆方法,用来创建并只允许创建一个实例。3公有化静态方法,用于向系统提供这个实例)
实例:
例1
class Singleton{
//存放实例
private static $_instance = null;
//私有化构造方法、
private function __construct(){
echo "单例模式的实例被构造了";
}
//私有化克隆方法
private function __clone(){
echo 'clone';
}
//公有化获取实例方法
public static function getInstance(){
if (!(self::$_instance instanceof Singleton)){
self::$_instance = new Singleton();
}
return self::$_instance;
}
}
$singleton=Singleton::getInstance();
页面输出:
单例模式的实例被构造了
三.注册树模式
定义:
注册树模式(Registry Pattern ):注册树模式为应用中经常使用的对象创建一个中央存储器来存放这些对象 —— 通常通过一个只包含静态方法的抽象类来实现(或者通过单例模式)。也叫做注册器模式
本质意义:
树相当于集合,保存对象资源。解决常用对象的存放问题,实现类似于全局变量的功能。
实例:
例1
//User类用于测试
class User{}
//注册树类
class Registry
{
protected static $objects; //用于存放实例
//存入实例方法
static public function set($key, $object)
{
self::$objects[$key] = $object;
}
//获取实例方法
static public function get($key)
{
if (!isset(self::$objects[$key]))
{
return false;
}
return self::$objects[$key];
}
//删除实例方法
static public function _unset($key)
{
unset(self::$objects[$key]);
}
}
$user = new User;
//存入实例
Registry::set('User',$user);
//查看实例
var_dump(Registry::get('User'));
//删除实例
Registry::_unset('User');
//再次查看实例
var_dump(Registry::get('User'));
页面输出:
object(User)#1 (0) { }
bool(false)
四.适配器模式
定义:
适配器模式(Adapter Pattern):将某个对象的接口适配为另一个对象所期望的接口。属于结构型设计模式
本质意义:
一个通用对象适配同类一批对象,只需要传不同参数,可以直接调用指定的对象。类结构一般保持一致。
实例:
例1
//MySQL待操作适配类
class MySQLAdaptee implements Target
{
protected $conn; //用于存放数据库连接句柄
//实现连接方法
public function connect($host, $user, $passwd, $dbname)
{
$conn = mysql_connect($host, $user, $passwd);
mysql_select_db($dbname, $conn);
$this->conn = $conn;
}
//查询方法
public function query($sql)
{
$res = mysql_query($sql, $this->conn);
return $res;
}
//关闭方法
public function close()
{
mysql_close($this->conn);
}
}
//MySQLi操作待适配类
class MySQLiAdaptee
{
protected $conn;
public function connect($host, $user, $passwd, $dbname)
{
$conn = mysqli_connect($host, $user, $passwd, $dbname);
$this->conn = $conn;
}
public function query($sql)
{
return mysqli_query($this->conn, $sql);
}
public function close()
{
mysqli_close($this->conn);
}
}
//用户所期待的接口
Interface Target{
public function connect($host, $user, $passwd, $dbname);
public function query($sql);
public function close();
}
//用户期待适配类
Class DataBase implements Target {
protected $db ; //存放MySQLiAdapter对象或MySQLAdapter对象
public function __construct($type){
$type = $type."Adapter" ;
$this->db = new $type ;
}
public function connect($host, $user, $passwd, $dbname){
$this->db->connect($host, $user, $passwd, $dbname);
}
public function query($sql){
return $this->db->query($sql);
}
public function close(){
$this->db->close();
}
}
//用户调用同一个接口,使用MySQL和mysqli这两套不同示例。
$db1 = new DataBase('MySQL');
$db1->connect('127.0.0.1','root','1234','myDB');die;
$db1->query('select * from test');
$db1->close();
$db2 = new DataBase('MySQLi');
$db2->connect('127.0.0.1','root','1234','myDB');
$db2->query('select * from test');
$db2->close();
四.观察者模式
定义:
观察者模式 (observer Pattern): 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。也叫发布-订阅模式
本质意义:
对象间的一种一对多的依赖关系。低耦合,高独立性,触发,高协调性。
代码实现:一个被观察者,对应多个观察者。被观察者一发生变化,观察者各自独立发生变化。
代码结构:
实例:被观察者定义功能实现类,被观察者发生变化类,观察者统一接口类,观察者独立功能类。
例1
//抽象被观察者
abstract class Subject{
//定义一个观察者数组
private $observers = array();
//增加观察者方法
public function addObserver(Observer $observer){
$this->observers[] = $observer;
echo "添加观察者成功<br>".PHP_EOL;
}
//删除观察者方法
public function delObserver(Observer $observer){
$key = array_search($observer,$this->observers); //判断是否有该观察者存在
if($observer===$this->observers[$key]) { //值虽然相同 但有可能不是同一个对象 ,所以使用全等判断
unset($this->observers[$key]);
echo '删除观察者成功<br>'.PHP_EOL;
} else{
echo '观察者不存在,无需删除<br>'.PHP_EOL;
}
}
//通知所有观察者
public function notifyObservers(){
foreach($this->observers as $observer){
$observer->update();
}
}
}
//具体被观察者 服务端
class Server extends Subject{
//具体被观察者业务 发布一条信息,并通知所有客户端
public function publish(){
echo '今天天气很好,我发布了更新包<br>'.PHP_EOL;
$this->notifyObservers();
}
}
//抽象观察者接口
Interface Observer{
public function update();
}
//具体观察者类
//微信端
class Wechat implements Observer{
public function update(){
echo '通知已接收,微信更新完毕<br>'.PHP_EOL;
}
}
//web端
class Web implements Observer{
public function update(){
echo '通知已接收,web端系统更新中<br>'.PHP_EOL;
}
}
//app端
class App implements Observer{
public function update(){
echo '通知已接收,APP端稍后更新<br>'.PHP_EOL;
}
}
header("Content-type: text/html; charset=utf-8");
//实例化被观察者
$server = new Server ;
//实例化观察者
$wechat = new Wechat ;
$web = new Web ;
$app = new App;
//添加被观察者
$server->addObserver($wechat);
$server->addObserver($web);
$server->addObserver($app);
//被观察者 发布信息
$server->publish();
//删除观察者
$server->delObserver($wechat);
//再次发布信息
$server->publish();
//尝试删除一个未添加成观察者的对象
$server->delObserver(new Web);
//再次发布信息
$server->publish();
页面输出:
添加观察者成功
添加观察者成功
添加观察者成功
今天天气很好,我发布了更新包
通知已接收,微信更新完毕
通知已接收,web端系统更新中
通知已接收,APP端稍后更新
删除观察者成功
今天天气很好,我发布了更新包
通知已接收,web端系统更新中
通知已接收,APP端稍后更新
观察者不存在,无需删除
今天天气很好,我发布了更新包
通知已接收,web端系统更新中
通知已接收,APP端稍后更新
五.策略模式
定义:
策略模式(Strategy Pattern):定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法独立于使用它的客户而变化,也称为政策模式(Policy)
本质意义:一个接口类,对应多种算法类。实现算法独立,算法解耦。
代码结构:一些算法类,一个抽象接口类,一个环境实现类。
实例:
例1
header("Content-type: text/html; charset=utf-8");
//抽象策略接口
abstract class Strategy{
abstract function peddle();
}
//具体封装的策略方法 女性用户策略
class ConcreteStrategyA extends Strategy
{
public function peddle(){
echo '美女穿这件衣服肯定很好看<br>'.PHP_EOL;
}
}
//男性用户策略
class ConcreteStrategyB extends Strategy
{
public function peddle(){
echo '每一个男人都需要一个工具箱,充实工具箱,从购买各种螺丝刀开始<br>'.PHP_EOL;
}
}
//未知性别用户策略
class ConcreteStrategyC extends Strategy
{
public function peddle(){
echo '骨骼清奇,这本《葵花宝典》最适合你<br>'.PHP_EOL;
}
}
//环境类
class Context{
protected $strategy;
public function __construct(Strategy $strategy)
{
$this->strategy = $strategy;
}
public function request()
{
$this->strategy->peddle($this);
}
}
//若处于女性用户环境
$female_context = new Context(new ConcreteStrategyA);
$female_context->request();
//若处于男性用户环境
$male_context = new Context(new ConcreteStrategyB);
$male_context->request();
//若处于未知性别用户环境
$unknow_context = new Context(new ConcreteStrategyC);
$unknow_context->request();
页面输出:
美女穿这件衣服肯定很好看
每一个男人都需要一个工具箱,充实工具箱,从购买各种螺丝刀开始
骨骼清奇,这本《葵花宝典》最适合你
六.装饰器模式
定义:
装饰器模式(Decorator Pattern): 允许向一个已有的对象添加新的功能或部分内容,同时又不改变其结构。属于结构型模式,它是作为现有的类的一个包装。
本质意义:提供非入侵式的类功能添加方案,实现类功能的添加以及混搭组合。(和继承方式的各个功能之间的关系 装饰器可并联可串联,继承只能串联 )
代码结构:
1.一个装饰器接口类
2.所有独立的装饰器接口类继承接口类
3.被装饰者类 添加装饰器类的添加,功能实现的方法。
实例:
例1
<?php
header("Content-type: text/html; charset=utf-8");
/游戏原来的角色类
class Person{
public function clothes(){
echo "长衫<br>".PHP_EOL;
}
}
/
//装饰器接口
interface Decorator
{
public function beforeDraw();
public function afterDraw();
}
//具体装饰器1-宇航员装饰
class AstronautDecorator implements Decorator
{
public function beforeDraw()
{
echo "穿上T恤<br>".PHP_EOL;
}
function afterDraw()
{
echo "穿上宇航服<br>".PHP_EOL;
echo "穿戴完毕<br>".PHP_EOL;
}
}
//具体装饰器2-警察装饰
class PoliceDecorator implements Decorator{
public function beforeDraw()
{
echo "穿上警服<br>".PHP_EOL;
}
function afterDraw()
{
echo "穿上防弹衣<br>".PHP_EOL;
echo "穿戴完毕<br>".PHP_EOL;
}
}
//被装饰者
class Person{
protected $decorators = array(); //存放装饰器
//添加装饰器
public function addDecorator(Decorator $decorator)
{
$this->decorators[] = $decorator;
}
//所有装饰器的穿长衫前方法调用
public function beforeDraw()
{
foreach($this->decorators as $decorator)
{
$decorator->beforeDraw();
}
}
//所有装饰器的穿长衫后方法调用
public function afterDraw()
{
// 装饰器调用反转
$decorators = array_reverse($this->decorators);
foreach($decorators as $decorator)
{
$decorator->afterDraw();
}
}
//装饰方法
public function clothes(){
$this->beforeDraw();
echo "穿上长衫<br>".PHP_EOL;
$this->afterDraw();
}
}
//警察装饰
echo "<br>警察装饰<br><br>".PHP_EOL;
$police = new Person;
$police->addDecorator(new PoliceDecorator);
$police->clothes();
//宇航员装饰
echo "<br>宇航员装饰<br><br>".PHP_EOL;
$astronaut = new Person;
$astronaut->addDecorator(new AstronautDecorator);
$astronaut->clothes();
//混搭风
echo "<br>混搭风<br><br>".PHP_EOL;
$madman = new Person;
$madman->addDecorator(new PoliceDecorator);
$madman->addDecorator(new AstronautDecorator);
$madman->clothes();
页面输出:
警察装饰
1穿上警服
穿上长衫
穿上防弹衣
穿戴完毕
宇航员装饰
穿上T恤
穿上长衫
穿上宇航服
穿戴完毕
混搭风
穿上警服
穿上T恤
穿上长衫
穿上宇航服
穿戴完毕
穿上防弹衣
穿戴完毕
六.原型模式
定义:
原型模式(Prototype Pattern):与工厂模式类似,都是用来创建对象的。利用克隆来生成一个大对象,减少创建时的初始化等操作占用开销
原因
1,有些时候,我们需要创建多个类似的大对象。如果直接通过new对象,开销很大,而且new完还得进行重复的初始化工作。可能把初始化工作封装起来的,但是对于系统来说,你封不封装,初始化工作还是要执行。
2,原型模式则不同,原型模式是先创建好一个原型对象,然后通过clone这个原型对象来创建新的对象,这样就免去了重复的初始化工作,系统仅需内存拷贝即可。
实例
例1
<?php
header("Content-type: text/html; charset=utf-8");
//抽象原型类
Abstract class Prototype{
abstract function clone();
}
//具体原型类
class Map extends Prototype{
public $width;
public $height;
public $sea;
public function setAttribute(array $attributes){
foreach($attributes as $key => $val){
$this->$key = $val;
}
}
public function clone(){}
}
//海洋类.这里就不具体实现了。
class Sea{}
//使用原型模式创建对象方法如下
//先创建一个原型对象
$map_prototype = new Map;
$attributes = array('width'=>40,'height'=>60,'sea'=>(new Sea));
$map_prototype->setAttribute($attributes);
//现在已经创建好原型对象了。如果我们要创建一个新的map对象只需要克隆一下
$new_map = clone $map_prototype;
echo '<pre>';
var_dump($map_prototype);
var_dump($new_map);
echo '</pre>';
页面输出:
object(Map)#1 (3) {
["width"]=>
int(40)
["height"]=>
int(60)
["sea"]=>
object(Sea)#2 (0) {
}
}
object(Map)#3 (3) {
["width"]=>
int(40)
["height"]=>
int(60)
["sea"]=>
object(Sea)#2 (0) {
}
}
七.中介者模式
中介者模式(Mediator Pattern): 用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。中介者模式又称为调停者模式,它是一种对象行为型模式。
本质意义:
对象之间不直接关联,通过第三方类关联。解决多对多关系线复杂的问题。(中介类)
代码结构:
抽象同事类一个,具体同事类多个。
抽象中介者类一个,具体中介者类一个。
实例:
例1
<?php
header("Content-type: text/html; charset=utf-8");
//抽象同事类 --------电话机
abstract class Colleague{
protected $mediator; //用于存放中介者
abstract public function sendMsg($num,$msg);
abstract public function receiveMsg($msg);
//设置中介者
final public function setMediator(Mediator $mediator){
$this->mediator = $mediator;
}
}
//具体同事类 ---------座机
class Phone extends Colleague
{
public function sendMsg($num,$msg)
{
echo class.'--发送声音:'.$msg.PHP_EOL;
$this->mediator->opreation($num,$msg);
}
public function receiveMsg($msg)
{
echo __class__.'--接收声音:'.$msg.PHP_EOL;
}
}
//具体同事类----------手机
class Telephone extends Colleague
{
public function sendMsg($num,$msg)
{
echo class.'--发送声音:'.$msg.PHP_EOL;
$this->mediator->opreation($num,$msg);
}
//手机接收信息前 会智能响铃
public function receiveMsg($msg)
{
echo '响铃-------'.PHP_EOL;
echo class.'--接收声音:'.$msg.PHP_EOL;
}
}
//抽象中介者类
abstract class Mediator{
abstract public function opreation($id,$message);
abstract public function register($id,Colleague $colleague);
}
//具体中介者类------交换机
class switches extends Mediator
{
protected $colleagues = array();
//交换机业务处理
public function opreation($num,$message)
{
if (!empty($num) && !array_key_exists($num,$this->colleagues)) {
//var_dump($num);
echo class.'--交换机内没有此号码信息,无法通话'.PHP_EOL;
}else{
$this->colleagues[$num]->receiveMsg($message);
}
}
//注册号码
public function register($num,Colleague $colleague)
{
if (!in_array($colleague, $this->colleagues)) {
$this->colleagues[$num] = $colleague;
}
$colleague->setMediator($this);
}
}
//实例化固话
$phone = new Phone;
//实例化手机
$telephone = new Telephone;
//实例化交换机
$switches = new Switches;
//注册号码 ---放号
$switches->register(6686668,$phone);
$switches->register(1881329,$telephone);
//通话
$phone->sendMsg(1881329,'hello world');
$telephone->sendMsg(6686668,'请说普通话');
$telephone->sendMsg(6686660,'你好');
页面输出:
Phone--发送声音:hello world
响铃-------
Telephone--接收声音:hello world
Telephone--发送声音:请说普通话
Phone--接收声音:请说普通话
Telephone--发送声音:你好
switches--交换机内没有此号码信息,无法通话