一  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. python学习之路(14)

    通过列表生成式,我们可以直接创建一个列表.但是,受到内存限制,列表容量肯定是有限的.而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素 ...

  2. pip & conda 换源

    conda换源方法具体参考清华大学镜像站Anaconda 镜像使用帮助 conda config --add channels https://mirrors.tuna.tsinghua.edu.cn ...

  3. HTML和CSS 入门系列(二):文字、表单、表格、浮动、定位、框架布局、SEO

    上一篇:HTML和CSS 入门系列(一):超链接.选择器.颜色.盒模式.DIV布局.图片 一.文字 1.1 属性 1.2 字体样式:font-family 1.3 字体大小:font-size 1.4 ...

  4. 第九周总结&实验报告七

    小结:这周请了一天的假,所以回来的时候有些知识点跟不上,不过在第二节课学到了关于IO的知识很重要,对于这次的实验也有些吃力,这周的知识点主要集中在书上,在各种不同条件下学习运用什么样的代码.   一. ...

  5. ContentLoadingProgressBar

    注意必须设置style: <android.support.v4.widget.ContentLoadingProgressBar android:id="@+id/progressB ...

  6. springboot+aop+自定义注解,打造通用的全局异常处理和参数校验切面(通用版)

    一.引入相应的maven依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifa ...

  7. 按模版导出Excel

    实现效果: excel模版: ExcelHandle.java package com.common.utils; import java.io.File; import java.io.FileIn ...

  8. windows+VS+Openjdk12 搭建debug环境

    openjdk12 下载地址: http://jdk.java.net/archive/ https://download.java.net/java/GA/jdk12/33/GPL/openjdk- ...

  9. golang RPC通信读写超时设置

    golang RPC通信中,有时候就怕读写hang住. 那是否可以设置读写超时呢? 1.方案一: 设置连接的读写超时 1.1 client RPC通信基于底层网络通信,可以通过设置connection ...

  10. web开发(二) Servlet中response、request乱码问题解决

    在网上看见一篇不错的文章,写的详细. 以下内容引用那篇博文.转载于<http://www.cnblogs.com/whgk/p/6412475.html>,在此仅供学习参考之用. 一.re ...