设计模式
1.单例模式
单例模式首先要满足三个条件:1.领有一个构造函数,并且为private 2.领有一个动态成员变量用来放弃类的实例 3.领有一个拜访这个实例的静态方法。
单例模式一个类只有一个实例,并提供一个拜访它的全局拜访入口。单例模式是在你想管制实例数目,节俭系统资源的时候应用。例如以下场景中:
1、一个党只能有一个书记。 2、Windows 是多过程多线程的,在操作一个文件的时候,就不可避免地呈现多个过程或线程同时操作一个文件的景象,所以所有文件的解决必须通过惟一的实例来进行。 3、一些设施管理器经常设计为单例模式,比方一个电脑有两台打印机,在输入的时候就要解决不能两台打印机打印同一个文件。
长处: 1、在内存里只有一个实例,缩小了内存的开销,尤其是频繁的创立和销毁实例(比方治理学院首页页面缓存)。 2、防止对资源的多重占用(比方写文件操作)。
咱们在extend目录下创立一个Single.php文件,以下是Single的内容。
咱们在index.php中创立一个getSingle办法
这时咱们发现,无论咱们调用多少次Single,new只执行一次。当$instance不存在的时候,就会new一个实例,当存在的时候就间接返回,最多执行一次new。
tp5框架用的单例模式在Container.php中,在thinkphp\library\think目录下。
2.注册树模式
注册树模式通过将对象实例注册到一颗全局的对象树上,须要的时候从对象树上采摘下来应用。
单例模式解决的是如何在整个我的项目中创立惟一对象实例的问题,工厂模式解决的是如何不通过new建设实例对象的办法。 那么注册树模式想解决什么问题呢? 在思考这个问题前,咱们还是有必要思考下前两种模式目前面临的局限。 首先,单例模式创立惟一对象的过程自身还有一种判断,即判断对象是否存在。存在则返回对象,不存在则创建对象并返回。 每次创立实例对象都要存在这么一层判断。 工厂模式更多思考的是扩大保护的问题。 总的来说,单例模式和工厂模式能够产生更加正当的对象。怎么不便调用这些对象呢?而且在我的项目内如此建设的对象如同散兵游勇一样,不便兼顾治理安顿啊。因 而,注册树模式应运而生。不论你是通过单例模式还是工厂模式还是二者联合生成的对象,都通通给我“插到”注册树上。我用某个对象的时候,间接从注册树上取 一下就好。这和咱们应用全局变量一样的不便实用。 而且注册树模式还为其余模式提供了一种十分好的想法。
接下来咱们进行注册树模式的实战解说,首先咱们在extend目录下创立一个TestRegister.php文件。在这个类外面咱们须要创立个注册树池子,而后创立几个办法,set()办法是把咱们的参数挂载在池子里,有两个参数,一个是$key,一个是$object。set办法的逻辑就是把$object填充到$objects[$key]中去。
get办法须要传入一个$key参数,咱们须要判断$objects[$key]中是否存在,如果不存在,就填入;如果存在就返回。
_unset办法同样传入$key参数,而后把$objects[$key]清空。
这就是一个简略的注册树模式的代码。残缺代码是这样的:
而后咱们进行应用层逻辑编写,同样在extend目录下创立一个A类,轻易输入点内容。
而后咱们在index.php外面创立一个办法,实例化A类,把A类挂在注册池外面。
如果咱们有多个相似于A的类,咱们就能够通过下面register办法一样去把它们挂在连接池外面。
依赖注入
依赖注入次要用来缩小代码间的耦合 无效拆散对象和它所需的内部资源,接下来咱们通过代码来对它进行了解。
首先咱们在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代码:
<?phpnamespace 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代码
<?phpnamespace 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代码
<?phpnamespace 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目录中。
以上就是容器类的简略实现。