您的位置:首页 > 编程语言 > PHP开发

PHP十二种设计模式

2015-05-31 10:53 639 查看
PSR-0规范的设计基础

1.全部使用命名空间

2.所有php文件必须自动载入,不能有include/require

spl_autoload_register

3.单一入口模式

1.三种基本的设计模式

工厂模式

用一个工厂方法去替换掉一个new

class Factory{

static function createDatabase(){

$db = new Database;

return $db;

}

}

使用的时候就可以用 $db = Factory::createDatabase();

单例模式

class Database{

private $db;

private function __construct(){

//这里可以写连接数据库

}

static function getInstance(){

if(self::$db){

return self::$db;

}else{

self::$db=new self()

return self::$db;//private可以自身调用

}

}

function where(){

}

}

如果是工厂加单例模式

class Factory{

static function createDatabase(){

$db = Database::getInstance();

return $db;

}

}

注册器(树)模式

class Register{

protected static $object;

static function set($alias,$object){

self::$object[$alias]=$object;

}

static function get($name)

{

return self::$object[$name];

}

function _unset($alias){

unset(self::$object[$alias]);

}

}

跟工厂方法结合

class Factory{

static function createDatabase(){

$db = Database::getInstance();

Register::set('db1',$db);

return $db;

}

}

索引直接调用

$db = Register::get('db1');

适配器模式

1.适配器模式,可以将截然不同的函数接口封装成统一的API

2.实际应用举例,PHP的数据库操作有mysql,mysqli,pdo3种,可以用适配器模式

统一成一致,类似的场景还有cache适配器,将memcache,redis,file,apc等不同的缓存函数,统一成一致,

比如说有一个Database.php里面有一个接口

interface IDatabase

{

function connect($host,$user,$pwd,$dbname);

function query($sql);

function close();

}

再下面有三个类

class mysql implements IDatabase{

private $con;

function connect($host,$user,$pwd,$dbname){

$this->con = mysql_connect($host,$user,$pwd);

mysql_select_db($dbname,$this->con);

}

function query($sql){

return mysql_query($sql,$this->con);

}

function close(){

return mysql_close($this->con);

}

}

class mysqli implements IDatabase{

protected $con;

function connect($host,$user,$pwd,$dbname)

{

$this->con = mysqli_connect($host,$user,$pwd,$dbname);

}

function query($sql)

{

return mysqli_query($this->con,$sql);

}

function close()

{

return mysqli_close($this->con);

}

}

class PDO implements IDatabase{

protected $con;

function connect($host,$user,$pwd.$dbname)

{

$con = new \PDO("mysql:host=$host;dbname=$dbname",$user,$pwd);

$this->con=$con;

}

function query($sql){

return $this->con->query($sql);

}

function close(){

unset($this->con);

}

}

这样我们调用的时候

$db = new mysql();或new mysqli();或new PDO();

$db->connect('127.0.0.1','root','root');

$db->query();

$db->close();

策略模式

将一组特定的行为和算法封装成类,以适应某些特定的上下文环境,这种模式就是策略模式

实际应用距离,假如一个电商系统的网站系统,针对男性女性用户要各自跳转到不同的商品类别

首先声明一个策略的接口文件

interface UserStrategy{

function showAd();

function showcategory();

}

//第一个策略 针对女性用户

class femaleUserStrategy implements UserStrategy{

function showAd(){

echo '2014新款女装';

}

function showCategory()

{

echo '女装';

}

}

//第二个策略,针对于男性用户

class maleUserStrategy implements UserStrategy{

function showAd(){

echo '2014新款男装';

}

function showCategory()

{

echo '男装';

}

}

//如果有一个page类

class page{

protected $strategy;

function index(){

$this->strategy->showAd();

$this->strategy->showCategory();

}

function setStrategy(\UserStrategt $strategy){

$this->strategy=$strategy;

}

}

$page = new Page();

if(isset($_GET['female'])){

$strategy = new femaleUserStrategy();

}else{

$strategy = new maleUserStrategy();

}

$page->setStrategy($strategy);

$page->index();

从一个硬编码到解耦的模式

数据对象映射模式

数据对象映射模式,是将对象和数据存储映射起来,对一个

对象的操作会映射为对数据存储的操作。

在代码中实现数据对象映射模式,我们将实现一个ORM类,将复杂的sql语句映射成对象属性的操作

class User{

public $id;

public $name;

public $mobile;

public $regtime;

protected $db;

function __construct($id){

//先取数据

$this->db = new mysql();

$this->db->connect('xxxxx'xxxx);

$res = $this->db->query('select * from XXX where id = {$id}');

$data = $res->fetch_assoc();

$this->id=$data['id'];

$this->name=$data['name'];

$this->mobile=$data['mobile'];

$this->regtime=$data['regtime'];

return $res;

}

function __destruct(){

//可以作为修改使用

$this->db->query('update xx set name={$this->name} mobile={$this->mobile}XXXXX where id = {$this->id}');

}

}

$user = new User(1);//1对应数据库中id为一

$user->mobile = '155555555';

$user->name='test';

$user->regtime=time();

//在这里没有sql语句.只有对对象的操作

综合运用(工厂模式,注册器模式,适配器模式)



观察者模式

1.观察者模式,当一个对象状态发生改变时,依赖他的对象全部会收到通知,并自动更新。

2.场景:一个事件发生后,要执行一连串更新操作,传统的编程方式,就

是在事件的代码之后直接加入处理逻辑,当更新的逻辑增多之后,代码会变得难以维护,这种方式是耦合的,侵入式的,

增加心的逻辑需要修改事件主体的代码

3.观察者模式实现了低耦合,非侵入式的通知更新机制。

demo

class Event{

function trigger(){

echo "Event";//表示事件发生了

//开始写更新逻辑了

echo '逻辑1';

echo '逻辑2';

echo '逻辑3';

}

}

$event = new Event();//传统的方式是耦合的,侵入式的,

//必须要改源码,所以我们定义一个观察者模式

demo

//在来一个接口

//先来一个基类抽象类

abstract class EventGenerator{

private $observers = array();

function addObserver(Observer$observer){

$this->obervers[]=$oberver;

}

function notify(){

foreach($this->obervers as $observer)

{

$observer->updata();

}

}

}

interface Oberver{

function update($event_info = null);

}

//所以说这个时候我们需要Event类继承这个基类

class Event extends EventGenerator{

function trigger(){

echo "Event";//表示事件发生了

$this->notify();

}

}

class Observer1 implements Observer{

function updata($event_info=null)

{

echo "逻辑一";

}

}

class Oberver2 implements Oberver{

function updata($event_info=null)

{

echo "逻辑二";

}

}

原型模式

1.与工厂模式作用类似,都是用来创建对象

2.与工厂模式的实现不同,原型模式先创建好一个原型

对象,然后通过clone原型对象来创建新的对象,这样就免去了类

创建时重复的初始化操作

3.原型模式适合于大对象的创建,创建一个大对象需要很大的开销,如果每次new就会消耗很大,

原型模式仅仅拷贝内存即可。

假如有一个画布类。new很复杂

我又想使用他两次

这样我们就可以用原型模式解决new的问题,用clone替代new

初始化之后直接clone即可。

装饰器模式

1.装饰器模式,可以动态的添加修改类的功能。

2.一个类提供了一项功能,如果要在修改并添加额外的功能,传统的

编程模式,需要写一个子类继承他,并重新实现类的方法。

3.使用装饰器模式,仅需在运行时添加一个装饰器对象即可实现,可以实现最大的灵活性

如果我们有一个画布类。只能打印一个正方形,假如我们想要添加一个颜色

一般是写一个子类,继承那个画布类。

重写产生画布的方法。那我们如果要增加很多功能呢?

是不是要重写很多类?

下面我们用装饰器模式解决这个问题

首先我们先声明一个画布的装饰器的接口

interface DrawDecorator{

function beforeDraw();

function afterDraw();

}

比如我们要修改画布类的draw()方法

所以我们在draw()方法中调用

function draw(){

$this->beforeDraw();

//这里是原来代码的内容

$this->afterDraw();

}

再在画布类中添加一个protected $decorators[]=array();

在添加一个方法,用来接收装饰器接口

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();

}

}

我们有一个颜色装饰器

class ColorDrawDecorator implements DrawDecorator{

protected $color;

function __construct($color='red')

{

$this->color= $color;

}

function beforDraw()

{

echo "<div style='color:{$this->color};'>";

}

function afterDraw()

{

echo "</div>"

}

}

在这里就不用去继承去实现了

$a = new canvas();//实例化画布类

$a -> init();//初始化

$a -> addDecorator(new colorDrawDecorator('green'));//添加一个颜色的装饰器类

迭代器模式

1.迭代器模式,在不需要了解内部实现的前提下,遍历yige

聚合对象的内部元素

2.相比传统的编程模式,迭代器模式可以隐藏遍历元素的所需的操作

比如遍历一个数据库,然后拿到所有对象

class Alluser implements Iterator{

protected $ids;

protected $index;//迭代器当前位置

protected $data=array();

//Iterator为迭代器接口

fucntion __construct(){

$db = Factory::getDatabase();

$result = $db->query("selecy id from user");

$this->ids = $db->mysql_fetch_assoc($result);

}

function current(){

//获取当前元素

$id=$this->ids[$this->index]['id'];

return Factory::getUser($id);

}

function next(){

//下一个元素

$this->index ++;

}

function valid()

{

//判断是否有数据

return $this->index < count($this->ids);

}

function rewind(){

$this->index=0;//第一步到开头

}

function key(){

//获取当前索引

return $this->index;

}

}

$users = new Alluser();

foreach ($users as $user)

{

var_dump($user);

}

代理模式

1.在客户端与实体之间建立一个代理对象(proxy),客户端对实体进行操作全部委派给代理对象,隐藏实体具体实现细节。

就是写一个

面向对象编程的基本原则

1.单一职责:一个类,只需要做好一件事情

2.开放封闭:一个类,应该是可扩展的,而不可修改的

3.依赖倒置:一个类,不应该强依赖另外一个类,每个类对于另外一个类都是可替换的

4.配置化:尽可能的使用配置,而不是硬编码。

5.面向接口编程:只需要关心接口,不需要关心实现。

MVC架构原理

我们先new 一个Config的对象

$config = new Config(__DIR__.'/configs');

$config['controller'];

那么有一个Config类

class Config implements \ArrayAccess{

//ArrayAccess接口是内置的接口,表示允许数组传值,其中有要实现四个方法

protected $path;

protected $configs=array();

function __construct($path)

{

$this->path=$path;

}

function offsetGet($key){

//获取该配置数组文件名key

if(empty($this->configs[$key]))

//如果原配置文件中不存在该数组文件名,那么就去加载

{

$file_path=$this->path.'/'.$key.'.php';//生成加载路径

$config = require $file_path;

$this->config[$key]=$config;

}

return $this->configs[$key];

}

function offsetSet($key,$value)

{

//设置数组的key

}

function offsetExists($key)

{ //检测数组的key是否存在

return isset($this->configs[$key]);

}

function offsetUnset($key)

{ //删除数组的key

}

}

配置文件比如controller.php

<?php

$config = array(

'home'=>array(

'decorator'=>array(

'IMooc\Dectorator\Template',

),

),

);

配置与设计模式

1.PHP中使用ArrayAccess实现配置文件的加载

2.在工厂方法中读取配置,生成可配置化的对象

3.使用装饰器模式实现权限验证,模板渲染,json串化

4.使用观察者模式实现数据更新事件的一系列更新操作

5.使用代理模式实现数据库的主从自动切换
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: