PHP开发自己的框架,你必须知道这些知识点!-php教程

资源魔 39 0

1、PHP罕用的四种数据构造

简介:spl是php的一个规范库。

民间文档:http://php.net/manual/zh/book.spl.php

<?php

//spl(php规范库)数据构造

/**
 * 栈(进步前辈后出)
 */
$stack = new SplStack();
$stack->push('data1');//入栈(进步前辈后出)
$stack->push('data2');//入栈
$stack->push('data3');//入栈

echo $stack->pop();//出栈
echo $stack->pop();//出栈
echo $stack->pop();//出栈


/**
 *行列步队(进步前辈先出)
 */
$queue = new SplQueue();
$queue->enqueue('data4');//入行列步队
$queue->enqueue('data5');//入行列步队
$queue->enqueue('data6');//入行列步队

echo $queue->dequeue();//出行列步队
echo $queue->dequeue();//出行列步队
echo $queue->dequeue();//出行列步队
echo $queue->dequeue();//出行列步队


/**
 * 堆
 */
$heap = new SplMinHeap();
$heap->insert('data8');//入堆
$heap->insert('data9');//入堆
$heap->insert('data10');//入堆

echo $heap->extract();//从堆中提取数据
echo $heap->extract();//从堆中提取数据
echo $heap->extract();//从堆中提取数据


/**
 * 固定命组(不管使没有应用,城市调配相应的内存空间)
 */
$array = new SplFixedArray(15);
$array['0'] = 54;
$array['6'] = 69;
$array['10'] = 32;
var_dump($array);

2、PHP链式操作的完成(原理)

一、入口文件 index.php

<?php
/**
 * 框架入口文件
 */
define('BASEDIR',__DIR__);//名目根目次
include BASEDIR.'/Extend/Loader.php';//引入名目主动加载类文件
spl_autoload_register('\\Extend\\Loader::autoload');//执行主动加载函数,实现类的主动加载


$db = new \Extend\Database();
$db->where('uid < 100000')->->order('uid desc')->limit(100);

二、主动加载类 Loader.php

<?php
namespace Extend;
/**
 * 完成框架的主动加载
 */
class Loader
{
    /**
     * 完成文件的主动载入
     */
    static function autoload($class)
    {
        require BASEDIR.'/'.str_replace('\\','/',$class).'.php';
    }


}

三、数据库类Database.php

注:只是原理,并无对办法进行详细的封装,详细的封装仍是看集体爱好去定链式查问的格调。

<?php
namespace Extend;

class Database
{
    /**
     * 指定查问前提
     * @param $where
     */
    function where($where)
    {
        return $this;
    }

    /**
     * 指定排序前提
     */
    function order($order)
    {
        return $this;
    }

    /**
     * 指定查问的限度条数
     * @param $limit
     */
    function limit($limit)
    {
        return $this;
    }


}

其实就是对传过去的前提进行从新的底层封装,而后再把以后工具前往,使患上能够一直的链式查问。

3、PHP魔术办法的应用

正在php设计模式中,会触及到不少魔术办法的应用,这里也对常常会用到的魔术办法进行简略总结。

一、框架入口文件 index.php

<?php
/**
 * 框架入口文件
 */
define('BASEDIR',__DIR__);//名目根目次
include BASEDIR.'/Extend/Loader.php';//引入名目主动加载类文件
spl_autoload_register('\\Extend\\Loader::autoload');//执行主动加载函数,实现类的主动加载


/**
 * 魔术办法的应用
 */

# 实例化Object类
$obj = new \Extend\Object();//以后文件没有存正在这个类,就会主动执行主动加载函数去蕴含相应的类文件(即 Extend/Object.php)


# __set 以及 __get 对没有存正在的属性进行接管
$obj->title = 'xiaobudiu'; //当对一个没有存正在的类属性赋值时,会主动挪用类中界说的__set()
echo $obj->title; //当挪用一个没有存正在的类属性时,会主动挪用类中界说的__get()


# __call 以及 __callStatic 对没有存正在或许权限不敷的类办法进行接管
$obj->getUserInfo('1000068'); //当挪用一个没有存正在的类办法时,会挪用__call(),并主动将以后办法名以及参数传到__call办法中
\Extend\Object::getOpenId('1000068'); //当挪用一个没有存正在的类动态办法时,会挪用__callStatic(),并主动将以后办法名以及参数通报到__callStatic办法中


# echo或print工具时,由__toString 接管
echo $obj; //当echo或print一个工具时,会主动挪用类中界说的__toString办法


# 正在php中,假如咱们把一个工具当成函数用,则由__invoke()接管
$obj('xiaobudiu');//当咱们将一个工具当成函数用的时分,会主动挪用以后类中界说的__invoke()办法

二、 Extend/Object.php

<?php
namespace Extend;
/**
 * 要求类名必需以及文件名放弃分歧,即类名是Object,则所正在文件名为Object.php
 * Class Object
 * @package Extend
 */
class Object
{
    protected $array = array();

    /**
     * 正在代码要给不决义的属性赋值时挪用,或正在类内部修正被private润饰的类属性时被挪用
     */
    function __set($name, $value)
    {
        echo "this is __set func";
    }

    /**
     * 当正在类内部拜访被private或proteced润饰的属性或拜访一个类华夏本没有存正在的属性时被挪用
     * @param $name
     */
    function __get($name)
    {
        echo "this is __get func";
    }

    /**
     * 当试图挪用没有存正在的办法或权限有余时会触发__call()
     * @param $name 挪用没有存正在的类办法时阿谁没有存正在的类办法的办法名
     * @param $arguments 挪用没有存正在的类办法时通报的参数
     */
    function __call($name, $arguments)
    {
        var_dump($name,$arguments);
    }


    /**
     * 当试图挪用没有存正在的动态办法或权限有余时会触发__callStatic()
     * @param $name 挪用没有存正在的动态办法时阿谁没有存正在的办法的办法名
     * @param $arguments 挪用没有存正在的动态办法时通报的参数
     */
    function __callStatic($name,$arguments)
    {
       var_dump($name,$arguments);
    }

    /**
     * 当应用echo或print打印工具时会挪用__toString()办法将工具转化为字符串
     */
    function __toString()
    {
        echo "this is __toString func";
    }


    /**
     * 工具自身不克不及间接当函数用,假如被当作函数用,会间接回调__invoke办法
     * @param $param
     */
    function __invoke($param)
    {
        echo $param."<br>this is __invoke func";
    }


}

4、三种根底设计模式

一、工场模式

经过传入参数的没有同,来实例化没有同的类。

index.php

<?php
/**
 * 框架入口文件
 */
define('BASEDIR',__DIR__);//名目根目次
include BASEDIR.'/Extend/Loader.php';//引入名目主动加载类文件
spl_autoload_register('\\Extend\\Loader::autoload');//执行主动加载函数,实现类的主动加载

//结构实例化缓存类时传入的参数
$config = array(
    'host' => '127.0.0.1',
    'pass' => 'myRedis&&&'
);
//工场模式创立cache工具
$cache = Extend\CacheFactory::getCacheObj('redis',$config);
var_dump($cache);

Extend/CacheFactory.php

<?php
namespace Extend;

class CacheFactory
{
    const FILE = 1;
    const MEMCACHE = 2;
    const REDIS = 3;

    static $instance;//界说动态属性,用于存储工具

    /**
     * 工场类创立缓存工具
     * @param $type 指定缓存类型
     * @param array $options 传入缓存参数
     * @return FileCache|Memcache|RedisCache
     */
    static function getCacheObj($type, array $options)
    {
        switch ($type) {
            case 'file':
            case self::FILE:
                self::$instance = new FileCache($options);
                break;

            case 'memcache':
            case self::MEMCACHE:
                self::$instance = new Memcache($options);
                break;

            case 'redis':
            case self::REDIS:
                self::$instance = new RedisCache($options);
                break;

            default:
                self::$instance = new FileCache($options);
                break;

        }
        return self::$instance;
    }
}

二、单例模式

保障一个类只实例化一个类工具,进而缩小零碎开支以及资本的糜费

index.php

<?php
/**
 * 框架入口文件
 */
define('BASEDIR',__DIR__);//名目根目次
include BASEDIR.'/Extend/Loader.php';//引入名目主动加载类文件
spl_autoload_register('\\Extend\\Loader::autoload');//执行主动加载函数,实现类的主动加载

//单例模式创立工具
$obj = Extend\SingleObject::getInstance();
$obj2 = Extend\SingleObject::getInstance();
var_dump($obj,$obj2);//从后果能够看出,两个实例化的工具实际上是一个工具

Extend/SingleObject.php

<?php
namespace Extend;

/**
 * 单例模式创立惟一类工具
 * Class SingleObject
 * @package Extend
 */
class SingleObject
{
    //公有的动态属性,用于存储类工具
    private static $instance = null;

    //公有的结构办法,保障没有容许正在类外 new
    private function __construct(){}

    //公有的克隆办法, 确保没有容许经过正在类外 clone 来创立新工具
    private function __clone(){}

    //私有的动态办法,用来实例化惟一以后类工具
    public static function getInstance()
    {
        if(is_null(self::$instance)){
            self::$instance = new self;
        }
        return self::$instance;
    }

}

三、注册示范式

将咱们用到的工具注册到注册树上,而后正在之后要用到这个工具的时分,间接从注册树上取上去就好。(就以及咱们用全局变量同样不便)

Extend/RegisterTree,php

<?php
namespace Extend;

/**
 * 注册示范式
 * Class RegisterTree
 * @package Extend
 */
class RegisterTree
{

    static protected $objects;//动态类属性,用于贮存注册到注册树上的工具

    /**
     * 将工具注册到注册树上
     * @param $alias 工具的别号
     * @param $object 工具
     */
    static function setObject($alias,$object)
    {
        self::$objects[$alias] = $object;
    }


    /**
     * 从注册树上掏出给定别号相应的工具
     * @param $alias 将工具拔出到注册树上时写的别号
     * @return mixed 工具
     */
    static protected function getObject($alias)
    {
        return self::$objects[$alias];
    }

    /**
     * 将工具从注册树上删除了
     * @param $alias 将工具拔出到注册树上时写的别号
     */
    public function unsetObject($alias)
    {
        unset(self::$objects[$alias]);
    }

}

5、其余常见的8种PHP设计模式

一、适配器模式

将一个类的接口转换成客户心愿的另外一个接口,适配器模式使患上本来的因为接口没有兼容而不克不及一同工作的那些类能够一同工作。
使用场景:老代码接口没有顺应新的接口需要,或许代码不少很乱方便于持续修正,或许应用第三方类库。

常见的有两种适配器,辨别是类适配器以及工具适配器,这里拿更看好的工具适配器举例:

<?php
namespace Extend;

/**
 * 工具适配器模式详细流程
 * 一、依据需要界说接口,进而餍足新需要性能
 * 二、界说新类,承继并完成界说的接口
 * 三、正在完成接口时,原本的性能,只经过原有类工具挪用原有类性能(委托)
 * 四、再依据需要,正在新类中完成新需要性能
 * 【实用性】
 * (1)你想应用一个曾经存正在的类,而它的接口没有合乎你的需要
 * (2)你想创立一个能够复用的类,该类能够与其余没有相干的类或不成预感的类协同工作
 * (3)你想应用一个曾经存正在的子类,然而不成能对每个都进行子类化以婚配它们的接口。工具适配器能够适配它的父类接口(仅限于对
 */


/**
 * 指标脚色(依据需要界说含有旧性能加之新性能的接口)
 * Interface Target 咱们希冀失去的性能类
 * @package Extend
 */
interface Target
{
    public function simpleMethod1();
    public function simpleMethod2();
}

/**
 * 源脚色(正在新性能提出以前的旧性能类以及办法)
 * Class Adaptee
 * @package Extend
 */
class Adaptee
{

    public function simpleMethod1()
    {
        echo 'Adapter simpleMethod1'."<br>";
    }

}

/**
 * 类适配器脚色(新界说接口的详细完成)
 * Class Adapter
 * @package Extend
 */
class Adapter implements Target
{

    private $adaptee;

    function __construct()
    {
        //适配器初始化间接new 原性能类,以不便之后委派
        $adaptee = new Adaptee();
        $this->adaptee = $adaptee;
    }

    //委派挪用Adaptee的sampleMethod1办法
    public function simpleMethod1()
    {
        echo $this->adaptee->simpleMethod1();
    }

    public function simpleMethod2()
    {
        echo 'Adapter simpleMethod2'."<br>";
    }

}

/**
 * 客户端挪用
 */
$adapter = new Adapter();
$adapter->simpleMethod1();
$adapter->simpleMethod2();

二、战略模式

将一组特定的行为以及算法封装成类,以顺应某些特定的上下文环境,这类模式就是战略模式,战略模式能够完成依赖颠倒和管制反转。

实例举例:如果一个电商网站零碎,针对男性女性用户要各自跳转到没有同的商品类目,而且一切的告白位展现展现没有同的告白。

index.php

<?php

/**
 * 框架入口文件
 */
define('BASEDIR',__DIR__);//名目根目次
include BASEDIR.'/Extend/Loader.php';//引入名目主动加载类文件
spl_autoload_register('\\Extend\\Loader::autoload');//执行主动加载函数,实现类的主动加载

/**
 * 首页数据管制器
 * Class Index
 */
class Home
{
    /**
     * 最佳写上这个正文,通知phpstorm是对应的哪一个接口类,不然尽管顺序执行正确,但phpstorm辨认没有了
     * @var \Extend\UserType
     */
    protected $userType;

    /**
     * 首页展现数据
     * 应用战略模式
     * Index constructor.
     */
    function index()
    {
        echo "AD:";
        $this->userType->showAd();
        echo "Category:";
        $this->userType->showCategory();
    }

    /**
     * 战略模式
     * 依据通报的用户性别展现没有同种别数据
     * @param \Extend\UserType $userType
     */
    function setUserType(\Extend\UserType $userType)
    {
        $this->userType = $userType;
    }

}

$obj = new Home();
if ($_GET['userType'] == 'female'){
    $userType = new \Extend\FemaleUserType();
} else {
    $userType = new \Extend\MaleUserType();
}
$obj->setUserType($userType);
$obj->index();

Extend/userType.php(界说的接口)

<?php

namespace Extend;

/**
 * 战略模式
 * 界说依据性别没有同展现没有同商品类目以及告白接口
 * Interface UserType
 * @package Extend
 */
interface UserType
{
    //显示告白
    function showAd();
    //展现类目
    function showCategory();

}

MaleUserType.php、FemaleUserType.php(详细完成的类 )

<?php

namespace Extend;

/**
 * 界说男性商品类目以及告白位数据接口
 * Class MaleUserType
 * @package Extend
 */
class MaleUserType implements UserType
{
    /**
     * 告白栏数据展现
     */
    function showAd()
    {
        echo "this is 男性’s 告白条款数据";
    }

    /**
     * 商品类目数据展现
     */
    function showCategory()
    {
        echo "this is 男性’s 商品类目数据";
    }

}
<?php

namespace Extend;

/**
 * 界说女性商品类目以及告白位数据接口
 * Class FemaleUserType
 * @package Extend
 */
class FemaleUserType implements UserType
{

    /**
     * 告白栏数据展现
     */
    function showAd()
    {
        echo "this is 女性’s 告白条款数据";
    }

    /**
     * 商品类目数据展现
     */
    function showCategory()
    {
        echo "this is 女性’s 商品类目数据";
    }


}

显示成果:

三、数据工具映照模式

将工具以及数据存储映照起来,对一个工具的操作会映照为对数据存储的操作。

上面正在代码中完成数据工具映照模式,咱们将完成一个ORM类,将复杂的sql语句映照成工具属性的操作。并连系应用数据工具映照模式、工场模式、注册模式。

-----(1)数据库映照模式简略实例完成

index.php

<?php
/**
 * 框架入口文件
 */
define('BASEDIR',__DIR__);//名目根目次
include BASEDIR.'/Extend/Loader.php';//引入名目主动加载类文件
spl_autoload_register('\\Extend\\Loader::autoload');//执行主动加载函数,实现类的主动加载

//应用数据工具映照模式替代写sql
$user = new Extend\User(25);
$user->name = '小卜丢饭团子';
$user->salary = '20000';
$user->city = '浙江省';

Extend/User.php

<?php

namespace Extend;

class User
{
    //对应数据库中的4个字段
    public $id;
    public $name;
    public $salary;
    public $city;
    //存储数据库衔接工具属性
    protected $pdo;

    public $data;

    function __construct($id)
    {
        $this->id = $id;
        $this->pdo = new \PDO('mysql:host=127.0.0.1;dbname=test','root','123456');
    }

    function __destruct()
    {
        $this->pdo->query("update user set name = '{$this->name}',salary = '{$this->salary}',city = '{$this->city}' where id='{$this->id}'");
    }
}

这样,执行index.php文件,数据库就会发作相应的操作,也就完成了根本的数据工具映照。

-------(2)数据库映照模式复杂案例完成

index.php

<?php

/**
 * 框架入口文件
 */
define('BASEDIR',__DIR__);//名目根目次
include BASEDIR.'/Extend/Loader.php';//引入名目主动加载类文件
spl_autoload_register('\\Extend\\Loader::autoload');//执行主动加载函数,实现类的主动加载


class EX
{
    function index()
    {
        //应用数据工具映照模式替代写sql
        $user = Extend\Factory::getUserObj(25);
        $user->name = '小卜丢饭团子';
        $user->salary = '20000';
        $user->city = '浙江省';
    }

    function test()
    {
        $user = Extend\Factory::getUserObj(25);
        $user->city = '广东省';
    }

}

$ex = new EX();
$ex->index();

Extend/Factory.php

<?php

namespace Extend;

class Factory
{
    /**
     * 工场模式创立数据库工具,单例模式保障创立惟一db工具
     * @return mixed
     */
    static function CreateDatabaseObj()
    {
        $db = Database::getInstance();
        return $db;
    }

    /**
     * 工场模式创立user工具,注册示范式保障创立惟一工具,防止资本糜费
     * @param $id
     * @return User|mixed
     */
    static function getUserObj($id)
    {
        $key = 'user'.$id;
        $user = RegisterTree::getObject($key);
        if (!$user) {
            $user = new User($id);
            RegisterTree::setObject($key,$user);
        }
        return $user;
    }
}

Extend/Register.php

<?php

namespace Extend;

/**
 * 注册示范式
 * Class RegisterTree
 * @package Extend
 */
class RegisterTree
{
    static protected $objects;//动态类属性,用于贮存注册到注册树上的工具

    /**
     * 将工具注册到注册树上
     * @param $alias 工具的别号
     * @param $object 工具
     */
    static function setObject($alias,$object)
    {
        self::$objects[$alias] = $object;
    }


    /**
     * 从注册树上掏出给定别号相应的工具
     * @param $alias 将工具拔出到注册树上时写的别号
     * @return mixed 工具
     */
    static function getObject($alias)
    {
        return self::$objects[$alias];
    }

    /**
     * 将工具从注册树上删除了
     * @param $alias 将工具拔出到注册树上时写的别号
     */
    public function unsetObject($alias)
    {
        unset(self::$objects[$alias]);
    }

}

Extend/User.php

<?php

namespace Extend;

class User
{
    //对应数据库中的4个字段
    public $id;
    public $name;
    public $salary;
    public $city;
    //存储数据库衔接工具属性
    protected $pdo;

    public $data;

    function __construct($id)
    {
        $this->id = $id;
        $this->pdo = new \PDO('mysql:host=127.0.0.1;dbname=test','root','123456');
    }

    function __destruct()
    {
        $this->pdo->query("update user set name = '{$this->name}',salary = '{$this->salary}',city = '{$this->city}' where id='{$this->id}'");
    }
}

这样,就完成了稍复杂的数据工具映照模式以及工场模式、注册示范式相连系的案例。

四、察看者模式

当一个工具状态发作扭转时,依赖它的工具会全副收到告诉,并主动更新。

场景:一个事情发作后,要执行一连串更新操作。传统的编程形式就是正在事情的代码之后间接退出解决逻辑,当更新的逻辑增多之后,代码会变的难以保护。这类形式是耦合的,侵入式的,添加新的逻辑需求修正事情主体的代码。察看者模式完成了低耦合,非侵入式的告诉与更新机制。

4.一、传统模式举例:

<?php

/**
 * 框架入口文件
 */
define('BASEDIR',__DIR__);//名目根目次
include BASEDIR.'/Extend/Loader.php';//引入名目主动加载类文件
spl_autoload_register('\\Extend\\Loader::autoload');//执行主动加载函数,实现类的主动加载


/**
 * 一个事情的逻辑管制器
 * Class Event
 */
class Event
{
    /**
     * 用户确认定单
     */
    function firmOrder()
    {
        //这里假定一个事情发作了,比方用户曾经实现下单
        echo "用户已下单<br>";
        //传统形式是正在发作一个事情之后间接进行一系列的相干解决,耦合度比拟高,比方写入日记,给用户发邮件等等
        echo "正在用户下单之落后行的一系列操作<br>";
    }

}

$event = new Event();
$event->firmOrder();

4.二、察看者模式典型完成形式:

(1)界说2个接口:察看者(告诉)接口、被察看者(主题)接口

(2)界说2个类,察看者类完成察看者接口、被察看者类完成被察看者接口

(3)被察看者注册本人需求告诉的察看者

(4)被察看者类某个营业逻辑发作时,告诉察看者工具,进而每一个察看者执行本人的营业逻辑。

代码示例:

test.php

<?php
/**
 * 察看者模式场景形容:
 * 一、购票跋文录文即日志
 * 二、购票跋文录数据库日记
 * 三、购票后发送短信
 * 四、购票送抵扣卷、兑换卷、积分
 * 五、其余各种流动等
 */


/**
 * 察看者接口
 */
interface TicketObserver
{
    function buyTicketOver($sender, $args); //失去告诉后挪用的办法
}

/**
 * 被察看者接口(购票主题接口)
 */
interface TicketObserved
{
    function addObserver($observer); //提供注册察看者办法
}


/**
 * 主体逻辑,承继被察看者接口
 * Class BuyTicket
 */
class BuyTicket implements TicketObserved
{

    /**
     * 界说察看者数组属性,用于贮存察看者
     * @var array
     */
    private $observers = array();


    /**
     * 完成被察看者接口界说的办法(增加察看者)
     * @param $observer 实例化后的察看者工具
     */
    public function addObserver($observer)
    {
        $this->observers[] = $observer;
    }


    /**
     * 购票主体办法
     * BuyTicket constructor.
     * @param $ticket 购票排号
     */
    public function buyTicket($ticket)
    {
        //一、依据需要写购票逻辑
        //..............

        //二、购票胜利之后,轮回告诉察看者,并挪用其buyTicketOver完成没有同营业逻辑
        foreach ($this->observers as $observe) {
            $observe->buyTicketOver($this, $ticket); //$this 可用来猎取主题类句柄,正在告诉中应用
        }

    }

}



/**
 * 购票胜利后,发送短信告诉
 * Class buyTicketMSN
 */
class buyTicketMSN implements TicketObserver
{
    public function buyTicketOver($sender, $ticket)
    {
        echo (date ( 'Y-m-d H:i:s' ) . " 短信日记记载:购票胜利:$ticket<br>");
    }
}

/**
 * 购票胜利后,记载日记
 * Class buyTicketLog
 */
class buyTicketLog implements TicketObserver
{
    public function buyTicketOver($sender, $ticket) 
    {
        echo (date ( 'Y-m-d H:i:s' ) . " 文即日志记载:购票胜利:$ticket<br>");
    }
}


/**
 * 购票胜利后,赠予优惠券
 * Class buyTicketCoupon
 */
class buyTicketCoupon implements TicketObserver
{
    public function buyTicketOver($sender, $ticket) 
    {
        echo (date ( 'Y-m-d H:i:s' ) . " 赠予优惠券:购票胜利:$ticket 赠予10元优惠券1张。<br>");
    }
}


//实例化购票类
$buy = new BuyTicket();
//增加多个察看者
$buy->addObserver(new buyTicketMSN());
$buy->addObserver(new buyTicketLog());
$buy->addObserver(new buyTicketCoupon());
//开端购票
$buy->buyTicket ("7排8号");

阅读器显示后果:

五、原型模式

原型模式与工场模式的作用相似,都是用来创立工具的。然而完成形式是没有同的。原型模式是先创立好一个原型工具,而后经过clone原型工具来创立新的工具。这样,就免去了类创立时反复的初始化操作。

原型模式实用于年夜工具的创立,创立一个年夜工具需求很年夜的开支,假如每一次new就会耗费很年夜,原型模式仅需内存拷贝便可。

代码实例:

<?php
/**
 * 形象原型脚色
 */
interface Prototype
{
    public function copy();
}

/**
 * 详细原型脚色
 */
class ConcretePrototype implements Prototype
{

    private $_name;

    public function __construct($name)
    {
        $this->_name = $name;
    }

    public function setName($name)
    {
        $this->_name = $name;
    }

    public function getName()
    {
        return $this->_name;
    }

    public function copy()
    {
        //深拷贝完成
         //$serialize_obj = serialize($this); // 序列化
         //$clone_obj = unserialize($serialize_obj); // 反序列化
         //return $clone_obj;

        // 浅拷贝完成
        return clone $this;
    }

}

/**
 * 测试深拷贝用的援用类
 */
class Demo
{
    public $array;
}


//测试
$demo = new Demo();
$demo->array = array(1, 2);
$object1 = new ConcretePrototype($demo);
$object2 = $object1->copy();

var_dump($object1->getName());
echo '<br />';
var_dump($object2->getName());
echo '<br />';

$demo->array = array(3, 4);
var_dump($object1->getName());
echo '<br />';
var_dump($object2->getName());
echo '<br />';

阅读器显示后果:

六、装璜器模式

能够静态的增加或修正类的性能

一个类完成一个性能,假如要再修正或增加额定的性能,传统的编程模式需求写一个子类承继它,并从新完成类的办法。

应用装璜器模式,仅需正在运转时增加一个装璜器工具便可完成,能够完成最年夜的灵敏性。

<?php
/**
 * 装璜器流程
 * 一、申明装璜器接口(装璜器接口)
 * 二、详细类承继并完成装璜器接口(颜色装璜器完成,字体巨细装璜器完成)
 * 三、正在被装璜者类中界说"增加装璜器"办法(EchoText类中的addDecorator办法)
 * 四、正在被装璜者类中界说挪用装璜器的办法(EchoText类中的beforeEcho以及afterEcho办法)
 * 五、应用时,实例化被装璜者类,并传入装璜器工具(比方new ColorDecorator('yellow'))
 */

/**
 * 装璜器接口
 * Class Decorator
 */
interface Decorator
{
    public function beforeEcho();
    public function afterEcho();
}

/**
 * 颜色装璜器完成
 * Class ColorDecorator
 */
class ColorDecorator implements Decorator
{
    protected $color;

    public function __construct($color)
    {
        $this->color = $color;
    }

    public function beforeEcho()
    {
        echo "<dis style='color: {$this->color}'>";
    }

    public function afterEcho()
    {
        echo "</p>";
    }
}

/**
 * 字体巨细装璜器完成
 * Class SizeDecorator
 */
class SizeDecorator implements Decorator
{
    protected $size;

    public function __construct($size)
    {
        $this->size = $size;
    }

    public function beforeEcho()
    {
        echo "<dis style='font-size: {$this->size}px'>";
    }

    public function afterEcho()
    {
        echo "</p>";
    }
}

/**
 * 被装璜者
 * 输入一个字符串
 * 装璜器静态增加性能
 * Class EchoText
 */
class EchoText
{
    protected $decorators = array();//寄存装璜器

    //装璜办法
    public function Index()
    {
        //挪用装璜器前置操作
        $this->beforeEcho();
        echo "你好,我是装璜器。";
        //挪用装璜器后置操作
        $this->afterEcho();
    }

    //增加装璜器
    public function addDecorator(Decorator $decorator)
    {
        $this->decorators[] = $decorator;
    }

    //执行装璜器前置操作 进步前辈先出准则
    protected function beforeEcho()
    {
        foreach ($this->decorators as $decorator)
            $decorator->beforeEcho();
    }

    //执行装璜器后置操作 进步前辈后出准则
    protected function afterEcho()
    {
        $tmp = array_reverse($this->decorators);
        foreach ($tmp as $decorator)
            $decorator->afterEcho();
    }
}

//实例化输入类
$echo = new EchoText();
//添加装璜器
$echo->addDecorator(new ColorDecorator('yellow'));
//添加装璜器
$echo->addDecorator(new SizeDecorator('22'));
//输入
$echo->Index();

七、迭代器模式

正在没有需求理解外部完成的条件下,遍历一个聚合工具的外部元素而又没有暴露该工具的外部示意,这就是PHP迭代器模式的界说。

绝对于传统编程模式,迭代器模式能够暗藏遍历元素的所需的操作。

index.php

<?php
/**
 * 框架入口文件
 */
define('BASEDIR',__DIR__);//名目根目次
include BASEDIR.'/Extend/Loader.php';//引入名目主动加载类文件
spl_autoload_register('\\Extend\\Loader::autoload');//执行主动加载函数,实现类的主动加载

$users = new Extend\AllUser();
//轮回遍历出一切用户数据
foreach ($users as $user) {
    var_dump($user);
}

Extend/AllUser.php

<?php
namespace Extend;

/**
 * 迭代器模式,承继php外部自带的迭代器接口(\Iterator)
 * Class AllUser
 * @package Extend
 */
class AllUser implements \Iterator
{
    protected $index = 0;//示意索引
    protected $ids = array();//用于贮存一切user的id(实际使用中,能够采纳注册示范式进行存储)
    protected $pdo;//用于存储数据库工具

    function __construct()
    {
        //猎取pdo数据库工具
        $this->pdo = new \PDO('mysql:host=127.0.0.1;dbname=test','root','123456');
        //猎取一切用户的id
        $this->ids = $this->pdo->query("select id from user")->fetchAll(2);
    }

    /**
     * 完成接口办法,重置迭代器,回到荟萃扫尾
     */
    public function rewind()
    {
        $this->index = 0;
    }

    /**
     * 完成接口办法,猎取以后元素
     * @return mixed|void
     */
    public function current()
    {
        $id = $this->ids[$this->index]['id'];
        //猎取以后用户的数据
        $user_data = $this->pdo->query("select * from user where id='{$id}'")->fetch(2);
        return $user_data;
    }

    /**
     * 完成接口办法,猎取以后元素键值
     * @return mixed|void
     */
    public function key()
    {
        return $this->index;
    }

    /**
     * 完成接口办法,猎取下一个元素
     */
    public function next()
    {
        $this->index++;
    }

    /**
     * 完成接口办法,验证能否另有下一个元素
     * @return bool|void
     */
    public function valid()
    {
        return $this->index < count($this->ids);
    }

}

八、代办署理模式

正在客户端与实体之间建设一个代办署理工具(proxy),客户端对实体进行操作全副委派给代办署理工具,暗藏实体的详细完成细节。

典型的使用就是mysql的主从构造,读写别离。正在mysql中,对一切读的操作申请从库,一切写的操作申请主库。

申明一个代办署理类,前台应用时只要创立一个代办署理类,挪用对应办法便可。代码实例:

index.php

<?php
/**
 * 框架入口文件
 */
define('BASEDIR',__DIR__);//名目根目次
include BASEDIR.'/Extend/Loader.php';//引入名目主动加载类文件
spl_autoload_register('\\Extend\\Loader::autoload');//执行主动加载函数,实现类的主动加载

// 一、传统编程模式是手动抉择
#查问操作应用从库
//$db_slave = Extend\Factory::getDatabase('slave');
//$info = $db_slave->query("select * from user where id = 1 limit 1");
#增删改操作应用主库
//$db_master = Extend\Factory::getDatabase('master');
//$db_master->query("update user name = 'xiaobudiu' where id = 29 limit 1");


// 二、应用代办署理模式
$db_proxy = new Extend\Proxy();
$db_proxy->getUserName(1);
$db_proxy->setUserName(29,'xiaobudiu');

Extend/Proxy.php

<?php
namespace Extend;

class Proxy implements IUserProxy
{
    function getUserName($id)
    {
        $db = Factory::getDatabase('slave');
        $db->query("select name from user where id =$id limit 1");
    }

    function setUserName($id, $name)
    {
        $db = Factory::getDatabase('master');
        $db->query("update user set name = $name where id =$id limit 1");
    }
}

Extend/Factory.php

<?php
namespace Extend;

class Factory
{
    static function getDatabase($id)
    {
        $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;
    }

}

Extend/Application.php

<?php
namespace Extend;

class Application
{
    public $base_dir;
    protected static $instance;

    public $config;

    protected function __construct($base_dir)
    {
        $this->base_dir = $base_dir;
        $this->config = new Config($base_dir.'/configs');
    }

    static function getInstance($base_dir = '')
    {
        if (empty(self::$instance))
        {
            self::$instance = new self($base_dir);
        }
        return self::$instance;
    }
    
}

Extend/Config.php

<?php
namespace Extend;

/**
 * 设置装备摆设类,承继于php自带的ArrayAccess接口
 * 容许一个工具以数组的形式拜访
 * Class Config
 * @package Extend
 */
class Config implements \ArrayAccess
{
    protected $path;
    protected $configs = array();

    function __construct($path)
    {
        $this->path = $path;
    }

    function offsetGet($key)
    {
        if (empty($this->configs[$key]))
        {
            $file_path = $this->path.'/'.$key.'.php';
            $config = require $file_path;
            $this->configs[$key] = $config;
        }
        return $this->configs[$key];
    }

    function offsetSet($key, $value)
    {
        throw new \Exception("cannot write config file.");
    }

    function offsetExists($key)
    {
        return isset($this->configs[$key]);
    }

    function offsetUnset($key)
    {
        unset($this->configs[$key]);
    }
}

configs/database.php

<?php
$config = array(
    'master' => array(
        'type' => 'MySQL',
        'host' => '127.0.0.1',
        'user' => 'root',
        'password' => '123456',
        'dbname' => 'test',
    ),
    'slave' => array(
        'slave1' => array(
            'type' => 'MySQL',
            'host' => '127.0.0.1',
            'user' => 'root',
            'password' => '123456',
            'dbname' => 'test',
        ),
        'slave2' => array(
            'type' => 'MySQL',
            'host' => '127.0.0.1',
            'user' => 'root',
            'password' => '123456',
            'dbname' => 'test',
        ),
    ),
);
return $config;

5、其他设计模式和总结

6、面向工具编程的根本准则

一、繁多职责准则:一个类只要要做好一件事件。没有要应用一个类实现不少性能,而应该拆分红更多更小的类。

二、开放关闭准则:一个类写好之后,应该是可扩大而不成修正的。

三、依赖颠倒准则:一个类不该该强依赖另一个类,每一个类关于另一个类都是可交换的。

四、设置装备摆设化准则:只管即便应用设置装备摆设,而没有是硬编码。

五、面向接口编程准则:只要要关怀某个类提供了哪些接口,而没有需求关怀他的完成。

7、主动加载设置装备摆设类文件

一、php中应用ArrayAccess完成设置装备摆设文件的加载(使患上顺序能够以数组的形式进行读取设置装备摆设)

(1)界说Config.php,承继php自带的ArrayAccess接口,并完成相应的办法,用于读取以及设置设置装备摆设

Extend/Config.php

<?php
namespace Extend;

/**
 * 设置装备摆设类,承继于php自带的ArrayAccess接口
 * 容许一个工具以数组的形式拜访
 * Class Config
 * @package Extend
 */
class Config implements \ArrayAccess
{
    protected $path;
    protected $configs = array();

    function __construct($path)
    {
        $this->path = $path;
    }

    function offsetGet($key)
    {
        if (empty($this->configs[$key]))
        {
            $file_path = $this->path.'/'.$key.'.php';
            $config = require $file_path;
            $this->configs[$key] = $config;
        }
        return $this->configs[$key];
    }

    function offsetSet($key, $value)
    {
        throw new \Exception("cannot write config file.");
    }

    function offsetExists($key)
    {
        return isset($this->configs[$key]);
    }

    function offsetUnset($key)
    {
        unset($this->configs[$key]);
    }
}

(2)configs/database.php

<?php
$config = array(
    'master' => array(
        'type' => 'MySQL',
        'host' => '127.0.0.1',
        'user' => 'root',
        'password' => '123456',
        'dbname' => 'test',
    ),
    'slave' => array(
        'slave1' => array(
            'type' => 'MySQL',
            'host' => '127.0.0.1',
            'user' => 'root',
            'password' => '123456',
            'dbname' => 'test',
        ),
        'slave2' => array(
            'type' => 'MySQL',
            'host' => '127.0.0.1',
            'user' => 'root',
            'password' => '123456',
            'dbname' => 'test',
        ),
    ),
);
return $config;

(3)读取设置装备摆设

index.php

<?php
/**
 * 框架入口文件
 */
define('BASEDIR',__DIR__);//名目根目次
include BASEDIR.'/Extend/Loader.php';//引入名目主动加载类文件
spl_autoload_register('\\Extend\\Loader::autoload');//执行主动加载函数,实现类的主动加载

$config = new Extend\Config(__DIR__.'/configs');
var_dump($config['database']);

(4)阅读器显示:

到此,就能够正在顺序中为所欲为的加载设置装备摆设文件了。

二、正在工场办法中读取设置装备摆设,天生可设置装备摆设化的工具

Extend/Factory.php

<?php
namespace Extend;

class Factory
{
    static function getDatabase($id)
    {
        $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;
    }

}

Extend/Application.php

<?php
namespace Extend;

class Application
{
    public $base_dir;
    protected static $instance;

    public $config;

    protected function __construct($base_dir)
    {
        $this->base_dir = $base_dir;
        $this->config = new Config($base_dir.'/configs');
    }

    static function getInstance($base_dir = '')
    {
        if (empty(self::$instance))
        {
            self::$instance = new self($base_dir);
        }
        return self::$instance;
    }

}

Extend/Config.php

<?php
namespace Extend;

/**
 * 设置装备摆设类,承继于php自带的ArrayAccess接口
 * 容许一个工具以数组的形式拜访
 * Class Config
 * @package Extend
 */
class Config implements \ArrayAccess
{
    protected $path;
    protected $configs = array();

    function __construct($path)
    {
        $this->path = $path;
    }

    function offsetGet($key)
    {
        if (empty($this->configs[$key]))
        {
            $file_path = $this->path.'/'.$key.'.php';
            $config = require $file_path;
            $this->configs[$key] = $config;
        }
        return $this->configs[$key];
    }

    function offsetSet($key, $value)
    {
        throw new \Exception("cannot write config file.");
    }

    function offsetExists($key)
    {
        return isset($this->configs[$key]);
    }

    function offsetUnset($key)
    {
        unset($this->configs[$key]);
    }
}

以上就是PHP开发本人的框架,你必需晓得这些常识点!的具体内容,更多请存眷资源魔其它相干文章!

标签: php php开发教程 php开发资料 php开发自学 框架开发

抱歉,评论功能暂时关闭!