一  trait

  php是单继承的语言,无法同时从两个基类中继承属性和方法,为了解决这个问题,php出了Trait这个特性.

个人理解的trait是: trait = abstract class - interface,其中拥有interface的多个继承的性质.'继承'的方式是 use trait;

二  单例模式

  单例模式确保类在全局只能有一个实例,因为它的实例是由自己保存,在类的外部也无法对该类进行实例化.PHP的单例模式是为了避免重复创建对象带来的资源消耗.

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

实际项目中像数据库查询,日志输出,全局回调,统一校验等模块。这些模块功能单一,但需要多次访问,如果能够全局唯一,多次复用会大大提升性能。

  • 单例类只能有一个实例
  • 单例类必须自己创建自己的唯一实例
  • 单例类必须给所有其他对象提供这一实例

三   trait与单例模式结合使用

  3.1 简单demo

    

trait Singleton
{
private static $instance; static function getInstance(...$args)
{
if(!isset(self::$instance)){
self::$instance = new static(...$args);
}
return self::$instance;
}
} class MySingleton
{
use Singleton;
} $mySingleton = Mysingleton::getInstance();

  3.2 为什么不用 new self()

  new self() 和 new static 的区别: 只有在继承中才能体现出来、如果没有任何继承、那么二者没有任何区别 然后 new self() 返回的实列是不会变的,无论谁去调用,都返回的一个类的实列, 而 new static则是由调用者决定的。

  此处如果用new self() ,那么我们获取到的对象就不是MySingleton了

  3.3 类,基类,trait之间同名函数的优先级

  先说结论,类 > trait > 基类,简单实例:

<?php
trait Dog{
public $name="dog";
public function drive(){
echo "This is dog drive";
}
public function eat(){
echo "This is dog eat";
}
} class Animal{
public function drive(){
echo "This is animal drive";
}
public function eat(){
echo "This is animal eat";
}
} class Cat extends Animal{
use Dog;
public function drive(){
echo "This is cat drive";
}
}
$cat = new Cat();
$cat->drive();
echo "<br/>";
$cat->eat(); ?>
得出:

This is cat drive
This is dog eat

  3.4 特殊情况,基类use trait,本类不use

trait A{
private static $instance;
static function getInstance()
{
if(!isset(self::$instance)){
self::$instance = new static();
}
return self::$instance;
}
} class B{
use A;
function a()
{
var_dump('call at B');
}
} class C extends B{
function a()
{
var_dump('call at c');
parent::a();
}
} class D extends B{
use A;
function a()
{
var_dump('call at D');
parent::a();
}
}
$b = B::getInstance();
$c = C::getInstance();
$d = D::getInstance(); $c->a();
$d->a();
得出:

string(9) "call at B"
string(9) "call at D"
string(9) "call at B"

  此时我们与疑问了,根据3.2所写,调用者是 C::getInstance();  怎么$c->a();像变成了 $b->a();一样呢???
(个人观点,也验证了)其实这里的$c,就是class B

  接下来进行验证:

trait A{
private static $instance;
static function getInstance()
{
if(!isset(self::$instance)){
self::$instance = new static();
}
return self::$instance;
}
} class B{
use A;function h(){
var_dump('h call at b');
} } class C extends B{function h(){
var_dump('h call at c');
}
}$b = B::getInstance();
$c = C::getInstance();$c->h();
得出:

string(11) "h call at b" 

  而我们去掉 class c 中的 h(), 会没有打印,验证了 这里的$c,就是class B 这句话.

  本篇就讲这么多,有兴趣的可以更深入了解trait与单例模式的知识点.

PHP trait与单例模式 (一次编写,到处使用)的更多相关文章

  1. 面试突击(六)——JVM如何实现JAVA代码一次编写到处运行的?

    声明:本文图片均来自网络,我只是进行了选择,利用一图胜千言的力量来帮助自己快速的回忆相关的知识点 JVM是 JAVA Virtual Machine 三个英文单词的首字母缩写,翻译成中文就是Java虚 ...

  2. 单例模式与pickle模块

    目录 设计模式之单例模式 pickle模块 设计模式之单例模式 设计模式是前辈们发明的经过反复验证用于解决固定问题的固定套路,在IT行业中设计模式总共有23种,可以分为三大类:创建型.结构型.行为型. ...

  3. golang面试-代码编写题1-14

    目录 1.代码编写题--统计文本行数-bufio 2.代码编写题--多协程收集错误信息-channel 3.代码编写题--超时控制,内存泄露 4.代码编写题--单例模式 5.代码编写题--九九乘法表 ...

  4. 很多个java面试题

    1. 为什么说Java是一门平台无关语言? 平台无关实际的含义是“一次编写到处运行”.Java 能够做到是因为它的字节码(byte code)可以运行在任何操作系统上,与底层系统无关. 2. 为什么 ...

  5. React Native:使用 JavaScript 构建原生应用

    [转载] 本篇为联合翻译,译者:寸志,范洪春,kmokidd,姜天意 数月前,Facebook 对外宣布了正在开发的 React Native 框架,这个框架允许你使用 JavaScript 开发原生 ...

  6. 【Spring】Spring AOP实现原理

    Spring AOP实现原理 在之前的一文中介绍过Spring AOP的功能使用,但是没有深究AOP的实现原理,今天正好看到几篇好文,于是就自己整理了一下AOP实现的几种方式,同时把代理模式相关知识也 ...

  7. 11.安装KVM虚拟机

    安装KVM虚拟机是一大难题,不按照虚拟机物理机128G内存和强劲的CPU无法充分利用.也不便于后面的jenkins自动部署.安装KVM虚拟机过程我是借鉴了网上下载的马哥linux   KVM那块的内容 ...

  8. 深入浅出 React Native:使用 JavaScript 构建原生应用

    深入浅出 React Native:使用 JavaScript 构建原生应用 链接:https://zhuanlan.zhihu.com/p/19996445 原文:Introducing React ...

  9. Java学习笔记之:Java简介

    一.引言 Java是由Sun Microsystems公司于1995年5月推出的Java面向对象程序设计语言和Java平台的总称.由James Gosling和同事们共同研发,并在1995年正式推出. ...

随机推荐

  1. C++入门经典-例6.15-通过字符串函数连接两个字符数组

    1:代码如下 // 6.15.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> using ...

  2. 剑指offer:把一个支付算转化为整数

    1:首先,根据课本上的程序,是这样的: #include "stdafx.h" #include "iostream" using namespace std; ...

  3. 移动端 iphone手机在中文情况下不执行keyup事件

    问题:移动端 在

  4. vue项目如何部署到Tomcat中

    vue项目如何部署到Tomcat中 1,假设你要访问的项目名称为'hms' 2,在Tomcat的webapps下创建hms文件夹, 3,配置config/index.js文件,build: {} 选项 ...

  5. mingw下的msys显示与输入乱码

    一直很喜欢gcc+vim这个貌似已经不用在强调了,好了,我只是想说明下我的问题是首先从gcc编译出错提示开始的 正如上面所说,安装完MinGW后使用gcc一编译,这程序没有错误还好,这一有错误发现输入 ...

  6. nagios配置邮件告警

    1.编辑配置文件 vim /etc/nagios/objects/contacts.cfg增加如下内容:define contactgroup{ contactgroup_name admins al ...

  7. 阶段3 3.SpringMVC·_01.SpringMVC概述及入门案例_03.入门程序之需求分析

  8. Docker 资源汇总

    Docker 资源汇总 Docker官方英文资源 Docker官网:http://www.docker.com Docker Windows 入门:https://docs.docker.com/do ...

  9. CSS 易混淆属性

    1. div中 height和line-height的区别 <div style="height:120px;">是用来规定整个div的高度,文字还是默认会在顶端开始向 ...

  10. Go语言mgo使用情况

    文重点介绍mgo使用,仅简单介绍mongodb. mongodb特性   mongdb简单介绍 注意: 上图已经告知我们mongo不支持事务,在开发项目应用时,想要保证数据的完整性请考虑关系型数据库( ...