内容简介:常用设计模式本文涉及的常用设计模式:单例模式、工厂模式、注册树模式单例模式(Singleton Pattern):顾名思义,就是只有一个实例。作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
常用设计模式
本文涉及的常用设计模式:单例模式、工厂模式、注册树模式
单例模式(Singleton Pattern):顾名思义,就是只有一个实例。作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
(1)为什么要使用 PHP 单例模式
1,php的应用主要在于数据库应用, 一个应用中会存在大量的数据库操作, 在使用面向对象的方式开发时, 如果使用单例模式,
则可以避免大量的new 操作消耗的资源,还可以减少数据库连接这样就不容易出现 too many connections情况。
2,如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看zend Framework的FrontController部分。
3,在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo
(2)单例模式的实现
1,私有化一个属性用于存放唯一的一个实例
2,私有化构造方法,私有化克隆方法,用来创建并只允许创建一个实例
3,公有化静态方法,用于向系统提供这个实例
工厂模式(Factor Pattern),就是负责生成其他对象的类或方法,也叫工厂方法模式
抽象工厂模式( Abstract Factor Pattern),可简单理解为工厂模式的升级版
(1)为什么需要工厂模式
1,工厂模式可以将对象的生产从直接new 一个对象,改成通过调用一个工厂方法生产。这样的封装,代码若需修改new的对象时,不需修改多处new语句,只需更改生产对象方法。
2,若所需实例化的对象可选择来自不同的类,可省略if-else多层判断,给工厂方法传入对应的参数,利用多态性,实例化对应的类。
注册树模式
注册树模式又称注册模式或注册器模式。注册树模式通过将对象实例注册到一棵全局的对象树上,需要的时候从对象树上采摘的模式设计方法。和果树不同的是,果子只能采摘一次,而注册树上的实例却可以无数次获取。
使用了注册树模式后,对于实例,我们能够更好地统筹管理安排,就像使用全局变量一样的方便实用。
接下来通过一段tp5中例子来实现上面的三个经典模式:
<?php /** * 单例模式 */ class Site { // 属性 public $siteName; // 本类的静态实例 protected static $instance = null; // 禁用掉构造器 private function __construct($siteName) { $this->siteName = $siteName; } // 获取本类的唯一实例 public static function getInstance($siteName = 'wuyudong') { if (! self::$instance instanceof self) { self::$instance = new self ( $siteName ); } return self::$instance; } } // 用工厂模式来生成本类的单一实例 class Factory { // 创建指定类的实例 public static function create() { return Site::getInstance ( "wu" ); } } /** * 对象注册树 * 1.注册:set(),把对象挂到树上 * 2.获取:get(), 把对象取下来用 * 3.注销:_unset(),把对象吃掉 */ class Register { // 创建对象池:数组 protected static $objects = [ ]; // 生成对象并上树 public static function set($alias, $object) { self::$objects [$alias] = $object; } // 从树上取下对象 public static function get($alias) { return self::$objects [$alias]; } // 把树上的对象吃掉 public static function _unset($alias) { unset ( self::$objects [$alias] ); } } // 将Site类的实例上树,放进对象池 Register::set ( 'site', Factory::create () ); // 从树上取一个对象 $obj = Register::get ( 'site' ); // 查看这个对象 var_dump ( $obj ); echo '<br/>';
容器与依赖注入的原理
1、任何的URL访问,最终都是定位到控制器,由控制器中某个具体的方法去执行
2、一个控制器对应一个类,如果这些类进行统一管理,怎么办?
通过容器来进行类管理,还可以将类的实例(对象)作为参数,传递给类方法,自动触发依赖注入
依赖注入:将对象类型的数据,以参数的方式传到方法的参数列表
URL访问:通过get方式将数据传到控制器指定的方法中(只能穿字符串、数值)
如果要传一个对象呢?
依赖注入:解决了向类中的方法传对象的问题
新建一个common目录,接着新建一个Temp.php文件,代码如下:
<?php namespace app\common; class Temp { private $name; public function __construct($name = 'wuyudong') { $this->name = $name; } public function setName($name) { $this->name = $name; } public function getName() { return '方法是:' . __METHOD__.'属性是:'.$this->name; } }
接着实现部分:
<?php namespace app\index\controller; use app\common\Temp; class Demo1 { // 通过字符串、数值用GET方式传值到类方法中 public function getName($name = 'Wu') { return 'Hello ' . $name; } public function getMethod1() { $temp = new Temp (); $temp->setName ( 'hezhijuan' ); return $temp->getName (); } // app\common\Temp $temp:将会触发依赖注入 public function getMethod2(Temp $temp) { $temp->setName ( 'hezhijuan' ); return $temp->getName (); } // 绑定一个类到容器 public function bindClass1() { // 把一个类放到容器中,相当于注册到容器 \think\Container::set ( 'temp', 'app\common\Temp' ); // 将容器中的类实例化并取出来使用:实例化时可调用构造器进行初始化 $temp = \think\Container::get ( 'temp', [ 'name' => 'hehehe' ] ); return $temp->getName (); } // 绑定一个类到容器(使用助手函数:bind和app) public function bindClass2() { // 把一个类放到容器中,相当于注册到容器 bind ( 'temp', 'app\common\Temp' ); // 将容器中的类实例化并取出来使用:实例化时可调用构造器进行初始化 $temp = app ( 'temp', [ 'name' => 'qwqw' ] ); return $temp->getName (); } // 绑定一个闭包到容器 public function bindClosure() { // 把一个闭包放到容器中 \think\Container::set ( 'demo', function ($domain) { return 'my blog site is:' . $domain; } ); // 将容器中的闭包取出来使用:实例化时可调用构造器进行初始化 $temp = \think\Container::get ( 'demo', [ 'domain' => 'www.wuyudong.com' ] ); return $temp; } }
Facade静态代理
门面(facade)为容器中的类提供了一个静态调用接口,相比于传统的静态方法调用, 带来了更好的可测试性和扩展
性,你可以为任何的非静态类库定义一个
facade 类。在common目录下新建一个Test.php文件,代码如下:
<?php namespace app\common; class Test { public function hello($name) { return 'Hello ' . $name; } }
常规动态调用代码如下:
namespace app\index\controller; class Demo2 { public function index($name = 'ThinkPHP') { $test = new \app\common\Test (); return $test->hello ( $name ); } }
如果想静态调用一个动态方法,需要给当前的类绑定一个静态代理类
新建目录facade,新建代理类Test.php,代码如下:
<?php namespace app\facade; use think\Facade; class Test extends Facade { protected static function getFacadeClass(){ return 'app\common\Test'; } }
这样
<?php namespace app\index\controller; use app\facade\Test; class Demo2 { public function index($name = 'ThinkPHP') { return Test::hello('wuyudong'); } }
即:app\facade\Test类代理了app\common\Test类
上面的实现还可以使用动态绑定:
修改facade\Test.php中的内容为:
<?php namespace app\facade; use think\Facade; class Test extends Facade { }
同样修改相应的代码,使用Facade的bind方法:
<?php namespace app\index\controller; use app\facade\Test; use think\Facade; class Demo2 { //动态绑定 public function index($name = 'ThinkPHP') { Facade::bind('app\facade\Test', 'app\common\Test'); return Test::hello('wuyudong'); } }
Request请求对象
方法1:可以使用上面所学的知识来进行Request对象的静态代理
<?php namespace app\index\controller; use think\Controller; use think\facade\Request; class Demo3 extends Controller { //创建一个请求对象Request的静态代理 public function test(){ dump(Request::get()); } }
方法2:常规方式:
<?php namespace app\index\controller; use think\Controller; use think\facade\Request; class Demo3 extends Controller { public function test(){ $request= new \think\Request(); dump($request->get()); } }
方法3:使用依赖注入的方式:
public function test(\think\Request $request){ dump($request->get()); }
方法4:使用Request类中的request属性:
public function test(){ dump($this->request->get()); }
方法5:使用助手函数request()来实现:
public function test(){ dump(request()->get()); }
这里使用5种方法实现Request对象的使用
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 设计模式之静态代理
- 静态库遇到静态库
- 全局变量,静态全局变量,局部变量,静态局部变量
- Android NDK秘籍--编译静态库、调用静态库
- static特别用法【静态导包】——Java包的静态导入
- c# – 为什么委托在静态方法中使用时不能引用非静态方法?
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Python编程快速上手
Albert Sweigart / 王海鹏 / 人民邮电出版社 / 2016-7-1 / 69.00元
如今,人们面临的大多数任务都可以通过编写计算机软件来完成。Python是一种解释型、面向对象、动态数据类型的高级程序设计语言。通过Python编程,我们能够解决现实生活中的很多任务。 本书是一本面向实践的Python编程实用指南。本书的目的,不仅是介绍Python语言的基础知识,而且还通过项目实践教会读者如何应用这些知识和技能。本书的首部分介绍了基本Python编程概念,第二部分介绍了一些不......一起来看看 《Python编程快速上手》 这本书的介绍吧!