我有一个类,几个方法都需要用到其它一个加解密类。
我是实例化一次然后用个变量(类的属性)存起来还是每次需要时再实例化好?
其实我是不太明白
require("class.php"); // 把可能需要的文件都在构造函数中 require 会影响性能吗?
new class();
两步发生了什么?
1
laoyuan 2015-06-14 12:06:19 +08:00
PHP 请求之间是独立的
|
2
shuimugan 2015-06-14 12:09:06 +08:00 1
可以写把你的类写成单例模式(就是不能直接new,在类的方法里new,只new一次),或者把加解密函数写成静态函数(不需要new,以 类::函数() 的方式调用)
require 的说明http://php.net/manual/zh/function.require.php |
3
raincious 2015-06-14 12:10:01 +08:00 2
呵呵。
你要是多次require的话,应该会提示redeclared class(之类)。最好用一个Autoloader来自动require,因为每次用一个Class的时候,PHP会检查这个Class是不是已经载入了,这样就不存在require冲突的问题了。(require_once是一个解法,但不是最优的) 另外至于是不是要new一个加密Class: 1、如果你的consturctor操作比较多,比较慢,或者根本没必要多次new,那么建立一个Singleton就好了。(protected/private construct,然后建立一个public static方法在内部new好,再缓存new出来的Instance) 2、如果你的consturctor操作不多,且Class中的数据需要用不同的Instance隔离,那么就必须new。 |
4
loveyu 2015-06-14 12:10:05 +08:00 1
性能基本无影响,就是这样玩的。
|
5
zakokun 2015-06-14 12:10:51 +08:00
单例
|
7
timsims 2015-06-14 12:25:27 +08:00 1
单例是反模式,不方便测试
楼主的意思,我的理解是: A类内有若干个方法需要调用B类 那么可以使用依赖注入,先把B类实例化后,作为参数传给A类的构造函数里 Class A { protected $bClass; public function __construct(B $bClass) { $this->$bClass = $bClass; } public function someMethod() { $this->$bClass->method(); } } class B { public function method(){} } $b = new B; $a = new A($b); |
8
iyaozhen OP |
9
ab 2015-06-14 12:34:59 +08:00
菜鸟问一下,为什么不include
|
10
iyaozhen OP @timsims 嗯嗯,就是这个意思。其实我现在做法是这样:
Class A { protected $bClass; public function someMethod1() { $this->$bClass = new B(); $this->$bClass->method1(); // $tmp = new B(); // $tmp->method1(); } public function someMethod2() { $this->$bClass->method2(); // $tmp = new B(); // $tmp->method2(); } } class B { public function method1(){} public function method2(){} } 因业务逻辑关系 someMethod1() 一定在 someMethod2() 前面调用。 注释里面的是每次都 new 的情况。 主要疑问就是 $this->$bClass 存着实例化的 class B 有什么坑吗?(class B 就是加解密,CPU 运算,没有涉及到 IO) |
11
iyaozhen OP @ab 因为是必须要引入的库,没引入的话流程进行不下去,所以用了 require。
require 和 include 几乎完全一样,除了处理失败的方式不同之外。require 在出错时产生 E_COMPILE_ERROR 级别的错误,换句话说将导致脚本中止。而 include 只产生警告(E_WARNING),脚本会继续运行。 |
12
timsims 2015-06-14 13:04:16 +08:00 1
@iyaozhen
实例化本身不存在什么坑,但是在类中去实例化对象就存在耦合问题(你这里就是A类的方法中new B),假如有一天你想把项目里所有class B都替换成class C,那就相当麻烦,这就是为什么我推荐通过依赖注入在A的构造函数里传入实例化后的B 不过我那个例子其实还不是最优的,最优的做法应该是注入一个接口,让B实现这个接口 具体还是看用代码说明。。 ``` Interface WhatEver { public function method1(); public function method2(); } Class A { protected $bClass; public function __construct(WhatEver $bClass) { $this->bClass = $bClass; } } class B implements WhatEver { public function method1(){} public function method2(){} } class C implements WhatEver { public function method1(){} public function method2(){} } $b = new B(); $a = new A($b); // 有一天你想把B无痛替换成C $c = new C(); $a = new A($c); // 就这么简单 ``` |
13
raincious 2015-06-14 13:08:28 +08:00 1
@iyaozhen
PHP干了啥,这你得探索下源代码了。 当然,语言的用户(PHP程序员)而言,如果不考虑构造函数的消耗,那么new一个对象的消耗是十分低的,你可以自己做个测试,让PHP建立上万个对象然后看看总耗时。 除非对象太多(取决于你的可用内存)可能会出现GC效能下降的问题(参见Composer那次),但就这个问题来说应该不会可能与到。 |
14
hitsmaxft 2015-06-14 13:16:38 +08:00 1
由于 php 的源代码(加载后编译成 opcode)在fpm 模式下,也算是资源而已。所以每次请求都不得不重新加载 class 所在的源代码。
在性能开销上考虑的话,可以引入 opcache 缓存扩展, 比如 zend opcache (5.5内置, 5.3和5.4 需要自行编译, apc 等其他老扩展的真心不推荐) 另外, 用 require 和 include 差别不大, 这种关键代码无论如何都不应该加载失败的。但注意 _once 系列函数别用。 至少在 apc 下是有 bug 的,这种函数是玩玩用的。 按需 new 或者单例,取决于这个实例的创建成本。这部分 @raincious 已经解释了 其实你的问题关键点不在 include , 而在 new XXclass() ; 会触发 查找类和调用 autoload 等等流程。 new XXX() -> XXX 不存在? -> 触发 autoload -> 类存在了?调用构造器 : 继续调用其他autoloader -> 还是没找到? 抛出异常 |
16
hahamy 2015-06-14 14:07:20 +08:00 1
如果class B有内在的逻辑,那么每次new B都是生成新的对象实例,相互之间不会影响,单例上一次对对象的操作,仍保留在对象内,下次调用的还是这个对象,所以看B的逻辑来做选择
|