Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

静态的应用场景 #13

Open
jiangshanmeta opened this issue Jul 1, 2017 · 0 comments
Open

静态的应用场景 #13

jiangshanmeta opened this issue Jul 1, 2017 · 0 comments
Labels

Comments

@jiangshanmeta
Copy link
Owner

静态属性和静态方法这两个概念大家都不陌生,然而在日常的开发中用的相对较少,结合最近的开发工作我想谈一谈我对这两个使用场景的理解。

静态方法的使用场景

首先是项目中的一个工具类。这个类收集了一些常用的工具函数,比如一些字符串处理函数、数组处理函数,本身各个方法之间没有什么逻辑关系,这个类更像是一个命名空间。其实这些方法我更倾向于按照面向过程的写法,写成一堆注册到全局的小函数。从逻辑上讲这里的每一个方法都不会影响实例的状态,所以均应该是静态方法,不过写成实例方法也没什么问题。

然后是model层的一个方法,这个方法是我封装来处理mongoId的,它本身也只是一个工具函数,不影响实例状态,而且最开始我还把这个方法直接final掉了,我不认为子类需要重载这个方法,这个方法最终声明成了静态方法。

对于静态方法和实例方法,我找到的资料一般认为性能上有些许差异,静态方法性能上更好一点点,其实可以认为没有差异。一般而言静态方法能做的实例方法都能做,然而实例方法能做的事情静态方法不一定能做(因为静态方法无法访问$this,无法改变实例状态)。我一直在提及的一个词是改变实例状态,这是我认为方法是否要加static修饰词的一个分界线,如果这个方法可能会改变实例状态,那么一定是实例方法,否则可当做静态方法。静态方法的一个特征是不允许子类重载,一定程度上相当于加上了final关键词(还是有不少差异的),我举的第二个例子就是把一个final的工具方法改成了静态方法。

静态方法和实例方法的应用场景上面已经总结了,下面介绍静态属性的应用场景。

静态属性的应用场景

首先是CI框架的conroller基类的一段代码

class CI_Controller {
	private static $instance;
	public function __construct(){
		self::$instance =& $this;
	}
	public static function &get_instance(){
		return self::$instance;
	}
}

利用静态私有变量$instance存储对象实例,然后通过静态方法get_instance获取实例,用过CI的应该对这段代码比较熟悉。

在这里静态变量存储了一个对象,基于类似的思路,我们可以实现单例模式

进一步扩展,静态变量不仅可以存储一个对象实例,也可以存储一组对象,下面就要自夸一段我自己写的代码了

class H_Model extends CI_Model{
	static private $_cache_models;
	public function __construct(){
		parent::__construct();
	}
	final protected function get_model($model){
		$_cache_name = strtolower($model);
		if(!isset(self::$_cache_models[$_cache_name]) || !(self::$_cache_models[$_cache_name] instanceof $model) ){
			self::$_cache_models[$_cache_name] = new $model;
		}
		return self::$_cache_models[$_cache_name];
	}
}

静态变量$_cache_models是配合方法get_model使用的,这段代码之所以出现是因为将代码从controller封装到model层的过程中,避免会在model层内部实例化其他model,这里将实例化的model保存在静态变量中避免不必要的实例化。

最后一段代码是用静态变量保存一组数组的,原理和上边保存一组对象差不多就不展示代码。最初是每个实例上都挂这么一个数组,当实例一多所占的内存就大了,后来我们改成用了一个global的变量存储这一组数组,然后每个对象对数组进行引用。但是从逻辑上不应该用global的元素保存,这些数组从属于类而不是全局,所以我改成了用静态存储。

可以看到,静态属性在存储对象/数组上有着特别的优势,用得好可以实现性能的优化、实现一些特殊的功能。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant