Maison > développement back-end > tutoriel php > PHP十二种设计模式

PHP十二种设计模式

WBOY
Libérer: 2016-06-23 13:33:40
original
916 Les gens l'ont consulté

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 "

";
}
function afterDraw()
{
  echo "
"
}
}
在这里就不用去继承去实现了
$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 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
$config = array(
    'home'=>array(
      'decorator'=>array(
              'IMooc\Dectorator\Template',
       ),
    ),
);


配置与设计模式
1.PHP中使用ArrayAccess实现配置文件的加载
2.在工厂方法中读取配置,生成可配置化的对象
3.使用装饰器模式实现权限验证,模板渲染,json串化
4.使用观察者模式实现数据更新事件的一系列更新操作
5.使用代理模式实现数据库的主从自动切换
Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal