您好,欢迎访问一九零五行业门户网

php精粹 php设计模式

1,选择一个最合适的设计模式
没有任何事物是完美的,也没有人说过设计模式一个严格的放之四海而皆准的解决方法。因此你可以改变这些模式,使它们更适合手头的工作。对于某些设计模式而言,他们就是所属程序固有的天性;而对于其他的一些设计模式,你可以改变其自身的模式。模式之间互相配合、协同工作已经很常见。它们构成了整个应用(至少一部分)的基础。
2.单例模式
// the database class represents our global db connection
class database{ // a static variable to hold our single instance private static $_instance = null; // make the constructor private to ensure singleton private function __construct() { echo 'constructor'; } // a method to get our singleton instance
public static function getinstance() { if (!(self::$_instance instanceof database)) { self::$_instance = new database(); } return self::$_instance; }}$database = database::getinstance();
var_dump($database);
复制代码
问题:使用单例模式不能创建两个实例,可用traits解决创建两个不同类型的实例的问题,但仍然不能解决创建两个相同实例的问题(可用注册表模式解决)。
创建两个不同类的实例 代码:
trait singleton { private static $_instance = null; public static function getinstance() { $class = __class__; if(!(self::$_instance instanceof $class)) { self::$_instance = new $class; } return self::$_instance; } } class db { } class dbwriteconnection extends db { use singleton; private function __construct() { echo 'dbwriteconnection
'; } } class dbreadconnection extends db { use singleton; private function __construct() { echo 'dbreadconnection
'; } } $dbwriteconnection = dbwriteconnection::getinstance(); var_dump($dbwriteconnection);
复制代码
3.注册表模式注册表模式仅仅是一个单独的全局类,在你需要的时候允许代码检索一个对象的相同实例,也可以在你需要的时创建另一个实例(一经要求将再次访问那些全局实例)。
registry类:
class registry {
/** * @var array the store for all of our objects */ static private $_store = array(); /** * add an object to the registry * * if you do not specify a name the classname is used * * @param mixed $object the object to store * @param string $name name used to retrieve the object * @return void * @throws exception */ static public function add($object, $name = null) { // use the classname if no name given, simulates singleton $name = (!is_null($name)) ?$name:get_class($object); if (isset(self::$_store[$name])) { throw new exception(object already exists in registry); } self::$_store[$name]= $object; } /** * get an object from the registry * * @param string $name object name, {@see self::set()} * @return mixed * @throws exception */ static public function get($name) { if (!self::contains($name)) { throw new exception(object does not exist in registry); } return self::$_store[$name];
} /** * check if an object is in the registry * * @param string $name object name, {@see self::set()} * @return bool */ static public function contains($name) { if (!isset(self::$_store[$name])) { return false; } return true; } /** * remove an object from the registry * * @param string $name object name, {@see self::set()} * @returns void */ static public function remove($name) { if (self::contains($name)) { unset(self::$_store[$name]); } }}
复制代码
在类外部,使用registry类:
require 'registry.php';
class dbreadconnection {}
class dbwriteconnection {}$read = new dbreadconnection;
registry::add($read);$write = new dbwriteconnection;
registry::add($write);// to get the instances, anywhere in our code:
$read = registry::get('dbreadconnection');$write = registry::get('dbwriteconnection');var_dump($read);
var_dump($write);
复制代码
在类内部使用registry表类,使用者不与registry交互。
示例代码:
require 'registry.php';
abstract class dbconnection {
static public function getinstance($name = null) { // get the late-static-binding version of __class__ $class = get_called_class(); // allow passing in a name to get multiple instances // if you do not pass a name, it functions as a singleton $name = (!is_null($name)) ? $name:$class; if (!registry::contains($name)) { $instance = new $class(); registry::add($instance, $name); } return registry::get($name); }}class dbwriteconnection extends dbconnection {
public function __construct() { echo 'dbwriteconnection
'; }}class dbreadconnection extends dbconnection {
public function __construct() { echo 'dbreadconnection
'; }}$dbwriteconnection = dbwriteconnection::getinstance('abc');
var_dump($dbwriteconnection);$dbreadconnection = dbreadconnection::getinstance();var_dump($dbreadconnection);
复制代码
4.工厂模式工厂(factory)模式制造对象,就像工业界与它同名的钢筋混泥土行业一样。通常,我们将工厂模式用于初始化相同抽象类或者接口的具体实现。
在通常方式下,虽然人们极少采用工厂模式,但是它仍是最适合初始化基于驱动安装的许多变种的一种。例如不同的配置、会话或缓存存储引擎。工厂模式的最大价值在于它可以将多个对象设置封装成单一、简单的方法调用。
/** * log factory * * setup and return a file, mysql, or sqlite logger */class log_factory { /** * get a log object * * @param string $type the type of logging backend, file, mysql or sqlite * @param array $options log class options */ public function getlog($type = 'file', array $options) { // normalize the type to lowercase $type = strtolower($type); // figure out the class name and include it $class = log_ .ucfirst($type); require_once str_replace('_', directory_separator, $class) . '.php'; // instantiate the class and set the appropriate options $log = new $class($options); switch ($type) { case 'file': $log->setpath($options['location']); break; case 'mysql': $log->setuser($options['username']); $log->setpassword($options['password']); $log->setdbname($options['location']); break; case 'sqlite': $log->setdbpath($otions['location']); break; } return $log; }}
复制代码
5.迭代模式迭代模式允许我们将foreach的性能添加到任何对象的内部存储数据,而不仅仅添加到公共属性。它覆盖了默认的foreach行为,并允许我们为循环注入业务逻辑。
(1)使用iterator迭代器接口
class basiciterator implements iterator {
private $key = 0; private $data = array( hello, world, ); public function __construct() {
$this->key = 0; } public function rewind() {
$this->key = 0; } public function current() {
return $this->data[$this->key]; } public function key() {
return $this->key; } public function next() {
$this->key++; return true; } public function valid() {
return isset($this->data[$this->key]); }}$iterator = new basiciterator();
$iterator->rewind();do {
$key = $iterator->key(); $value = $iterator->current(); echo $key .': ' .$value . php_eol;} while ($iterator->next() && $iterator->valid());
$iterator = new basiciterator();foreach ($iterator as $key => $value) { echo $key .': ' .$value . php_eol;}
复制代码
(2)使用recursiveiteratoriterator迭代器遍历数组
$array = array(
hello, // level 1 array( world // level 2 ), array( how, // level 2 array( are, // level 3 you // level 3 ) ), doing? // level 1);$recursiveiterator = new recursivearrayiterator($array);
$recursiveiteratoriterator = new recursiveiteratoriterator($recursiveiterator);
foreach ($recursiveiteratoriterator as $key => $value) {
echo depth: . $recursiveiteratoriterator->getdepth() . php_eol; echo key: . $key . php_eol; echo value: .$value . php_eol;}
复制代码
(3)用filteriterator迭代器实现过滤
getinneriterator(); // get the current key $key = $iterator->key(); // check for even keys if ($key % 2 == 0) { return true; } return false; }}$array = array(
0 => hello, 1 => everybody is, 2 => i'm, 3 => amazing, 4 => the, 5 => who, 6 => doctor, 7 => lives);// create an iterator from our array
$iterator = new arrayiterator($array);// create our filteriterator
$filteriterator = new evenfilteriterator($iterator);// iterate
foreach ($filteriterator as $key => $value) { echo $key .': '. $value . php_eol;}?>
复制代码
(4)regexiterator迭代器
$file) { /* @var splfileinfo $file */ echo $file->getfilename() . php_eol;}
复制代码
功能:找到所有的php文件
(4)limititertor迭代器,像sql中的limit
// define the array
$array = array( 'hello', 'world', 'how', 'are', 'you', 'doing?');// create the iterator
$iterator = new arrayiterator($array);// create the limiting iterator, to get the first 2 elements
$limititerator = new limititerator($iterator, 0, 2);// iterate
foreach ($limititerator as $key => $value) { echo $key .': '. $value . php_eol;}
复制代码
6.观察者模式(observer)
观察者模式的核心在于云霄你的应用程序注册一个回调,当某个特定的事件发生时便会促发它
callbacks */ static protected $callbacks = array(); /** * register a callback * * @param string $eventname name of the triggering event * @param mixed $callback an instance of event_callback or a closure */ static public function registercallback($eventname, $callback) { if (!($callback instanceof event_callback) && !($callback instanceof closure)) { throw new exception(invalid callback!); } $eventname = strtolower($eventname); self::$callbacks[$eventname][] = $callback; } /** * trigger an event * * @param string $eventname name of the event to be triggered * @param mixed $data the data to be sent to the callback */ static public function trigger($eventname, $data) { $eventname = strtolower($eventname); if (isset(self::$callbacks[$eventname])) { foreach (self::$callbacks[$eventname] as $callback) { self::callback($callback, $data); } } } /** * perform the callback * * @param mixed $callback an instance of event_callback or a closure * @param mixed $data the data sent to the callback */ static protected function callback($callback, $data) { if ($callback instanceof closure) { $callback($data); } else { $callback->run($data); } }}/**
* the event callback interface * * if you do not wish to use a closure * you can define a class that extends * this instead. the run method will be * called when the event is triggered. */interface event_callback { public function run($data);}/**
* logger callback */class logcallback implements event_callback { public function run($data) { echo log data . php_eol; var_dump($data); }}// register the log callback
event::registercallback('save', new logcallback());// register the clear cache callback as a closure
event::registercallback('save', function ($data) { echo clear cache . php_eol; var_dump($data); });class mydatarecord {
public function save() { // save data // trigger the save event event::trigger('save', array(hello, world)); }}// instantiate a new data record
$data = new mydatarecord();$data->save(); // 'save' event is triggered here
复制代码
7.依赖注入模式依赖注入模式允许类的使用这为这个类注入依赖的行为。
/**
* log class */class log { /** * @var log_engine_interface */ protected $engine = false; /** * add an event to the log * * @param string $message */ public function add($message) { if (!$this->engine) { throw new exception('unable to write log. no engine set.'); } $data['datetime'] = time(); $data['message'] = $message; $session = registry::get('session'); $data['user'] = $session->getuserid(); $this->engine->add($data); } /** * set the log data storage engine * * @param log_engine_interface $engine */ public function setengine(log_engine_interface $engine) { $this->engine = $engine; } /** * retrieve the data storage engine * * @return log_engine_interface */ public function getengine() { return $this->engine; }}interface log_engine_interface {
/** * add an event to the log * * @param string $message */ public function add(array $data);}class log_engine_file implements log_engine_interface {
/** * add an event to the log * * @param string $message */ public function add(array $data) { $line = '[' .data('r', $data['datetime']). '] ' .$data['message']. ' user: ' .$data['user'] . php_eol; $config = registry::get('site-config'); if (!file_put_contents($config['location'], $line, file_append)) { throw new exception(an error occurred writing to file.); } }}$engine = new log_engine_file();
$log = new log();
$log->setengine($engine);// add it to the registry
registry::add($log);
复制代码
依赖注入不想工厂模式,日之类无需了解每一个不同的存储引擎的相关知识。这就意味着任何使用日志类的开发者可以添加他们自己的存储引擎,主要他们复合接口就行。
8.模型-视图-控制器模型-视图-控制器又称为mvc模式,是描述应用程序3个不同层次之间关系的一种方式。模型-数据层 所有的输出数据都来自模型。它可能是一个数据库、web服务或者文件。视图-表现层 负责将数据从模型中取出并输出给用户。控制器-应用程序流层 根据用户的请求调用相应的模型检索出请求的数据,然后调用视图将操作的结果显示给用户。
一个典型的mvc架构图:
9.对模式的理解
模式是很多常见问题的最佳解决方法。
您可能感兴趣的文章:php设计模式之单例模式、工厂模式与观察者模式 深入php设计模式实例详解 php设计模式实例之命令模式 php设计模式实例之观察者模式(2) php设计模式实例之观察者模式 php设计模式实例之工厂模式 php设计模式实例之单例模式 php设计模式之观察者模式的例子 php设计模式之工厂模式的实例代码 php设计模式之单例模式的实例代码 php常用设计模式之工厂模式与单例模式介绍 学习php设计模式之单例模式 php常用的三种设计模式的学习笔记 php设计模式之单例模式学习
其它类似信息

推荐信息