单例模式首先要知足三个条件:1.拥有一个构造函数,而且为private 2.拥有一个静态成员变量用来保持类的实例 3.拥有一个访问这个实例的静态方法。
单例模式一个类只有一个实例,并提供一个访问它的全局访问入口。单例模式是在你想控制实例数目,节省系统资源的时候使用。例如如下场景中:
一、一个党只能有一个书记。 二、Windows 是多进程多线程的,在操做一个文件的时候,就不可避免地出现多个进程或线程同时操做一个文件的现象,因此全部文件的处理必须经过惟一的实例来进行。 三、一些设备管理器经常设计为单例模式,好比一个电脑有两台打印机,在输出的时候就要处理不能两台打印机打印同一个文件。
优势: 一、在内存里只有一个实例,减小了内存的开销,尤为是频繁的建立和销毁实例(好比管理学院首页页面缓存)。 二、避免对资源的多重占用(好比写文件操做)。
咱们在extend目录下建立一个Single.php文件,如下是Single的内容。
咱们在index.php中建立一个getSingle方法
这时咱们发现,不管咱们调用多少次Single,new只执行一次。当$instance不存在的时候,就会new一个实例,当存在的时候就直接返回,最多执行一次new。
tp5框架用的单例模式在Container.php中,在thinkphp\library\think目录下。php
注册树模式经过将对象实例注册到一颗全局的对象树上,须要的时候从对象树上采摘下来使用。
单例模式解决的是如何在整个项目中建立惟一对象实例的问题,工厂模式解决的是如何不经过new创建实例对象的方法。 那么注册树模式想解决什么问题呢? 在考虑这个问题前,咱们仍是有必要考虑下前两种模式目前面临的局限。 首先,单例模式建立惟一对象的过程自己还有一种判断,即判断对象是否存在。存在则返回对象,不存在则建立对象并返回。 每次建立实例对象都要存在这么一层判断。 工厂模式更多考虑的是扩展维护的问题。 总的来讲,单例模式和工厂模式能够产生更加合理的对象。怎么方便调用这些对象呢?并且在项目内如此创建的对象好像散兵游勇同样,不便统筹管理安排啊。因 而,注册树模式应运而生。无论你是经过单例模式仍是工厂模式仍是两者结合生成的对象,都通通给我“插到”注册树上。我用某个对象的时候,直接从注册树上取 一下就好。这和咱们使用全局变量同样的方便实用。 并且注册树模式还为其余模式提供了一种很是好的想法。
接下来咱们进行注册树模式的实战讲解,首先咱们在extend目录下建立一个TestRegister.php文件。在这个类里面咱们须要建立个注册树池子,而后建立几个方法,set()方法是把咱们的参数挂载在池子里,有两个参数,一个是$key,一个是$object。set方法的逻辑就是把$object填充到$objects[$key]中去。thinkphp
get方法须要传入一个$key参数,咱们须要判断$objects[$key]中是否存在,若是不存在,就填入;若是存在就返回。设计模式
_unset方法一样传入$key参数,而后把$objects[$key]清空。
这就是一个简单的注册树模式的代码。完整代码是这样的:
而后咱们进行应用层逻辑编写,一样在extend目录下建立一个A类,随便输出点内容。
而后咱们在index.php里面建立一个方法,实例化A类,把A类挂在注册池里面。缓存
若是咱们有多个相似于A的类,咱们就能够经过上面register方法同样去把它们挂在链接池里面。php框架
依赖注入主要用来减小代码间的耦合 有效分离对象和它所需的外部资源,接下来咱们经过代码来对它进行理解。
首先咱们在extend目录下建立一个di目录,di目录里建立一个Person类,而后建立一个buy方法。接着再建立一个Car类,在里面建立一个pay方法,而后返回价格。在buy方法里面调用Car类里面的pay方法。
而后咱们在入口文件里面建立一个方法,而后调用Person类的buy方法。
这样就能够把Car类里面的pay方法调用了。这就是一个简单的依赖注入例子了。
其中Person类依赖于Car类,而后Car类注入到Person类中,由于person去买东西,不必定要买Car,还有其余物品,这时就要把买的物品注入到Person类中去。这个时候问题来了,若是咱们buy的东西是其余物品,而不是Car,那咱们就要对代码进行修改了。修改以下:
首先把Person类里面的buy方法修改,以前咱们写的是指定的Car,这个时候咱们就要把指定的Car换成须要购买的物品,代码以下,直接传入对象,而后经过传入的对象进行调用。
在入口文件的方法中,咱们直接建立一个须要用到的实例,而后传给Person的方法。
这里我new了一个Car类,若是咱们须要的不是Car类,而是其余的类,那咱们就把Car换成须要的类。多线程
反射机制是在php5.0以后的版本增长的一个特性,这个特性给咱们提供了一个强大的API,容许咱们在php运行环境中去访问和使用类、方法、属性、参数和注释,它的功能是很是强大的,常常用于高扩展的php框架,自动加载插件、生成文档。好比说咱们进行生成php里面的注释等,就是经过php里的反射机制进行的,甚至能够用来扩展php语言。反射机制里面有许多方法,咱们能够根据文档去查看各类方法的用途,文档连接:php反射机制连接。在咱们使用反射机制的时候,首先要对类进行实例化,而后实例化类的反射机制,接下来进行调用这些方法。框架
接下来咱们对上面的知识进行综合性的实践,建立一个简单的容器类。
咱们进行操做的文件有如下几个文件,首先是容器类Container,而后是Person类和Car类,最后是应用层index.php入口文件。
首先是容器类Container代码:函数
<?php namespace di; class Container { /* * 存放数据的容器 * */ public $instances = []; /* * 容器中的对象实例 * */ protected static $instance; private function __construct() { } /* * 获取当前容器的实例(单例) * * */ public static function getInstance(){ if (is_null(static::$instance)){ static::$instance = new static; } return static::$instance; } public function set($key,$value){ $this->instances[$key] = $value; } /* * 获取容器里面的实例 会用到反射机制 * */ public function get($key){ if(!empty($this->instances[$key])) { $key = $this->instances[$key]; } $reflect = new ReflectionClass($key); //获取类的构造函数 $c = $reflect->getConstructor(); if (!$c){ return new $key; } $params = $c->getParameters(); // dump($params);exit(); if (empty($params)){ return new $key; }else{ foreach ($params as $param){ $class = $param->getClass(); if (!$class){ }else{ $args[] = $this->get($class->name); } } } return $reflect->newInstanceArgs($args); } }
而后是Person代码this
<?php namespace di; class Person { public function __construct(Car $obj,$a = 124) { $this->obj = $obj; $this->a = $a; } /* * 依赖:Person类依赖于Car * 注入 Car类注入到Person * */ public function buy(){ return $this->a . "|" . $this->obj->pay(); } }
Car代码spa
<?php namespace di; class Car { public function pay(){ return 123; } }
而后是index入口文件的方法代码:
public function buy(){ Container::getInstance()->set("person","diPerson"); Container::getInstance()->set("car","diCar"); $obj = Container::getInstance()->get("person"); dump($obj->buy()); }
其中Person、Car、Container都在extend目录下的di目录中。
以上就是容器类的简单实现。