首页 > php学习 > php基础知识 > OOP中的单例模式工厂模式和类型约束
2016
12-16

OOP中的单例模式工厂模式和类型约束

单例模式:

一个类在语法上实例化无数个对象,但是有些情况下一个类的一个实例化对象就可以完成所有功能(如数据库连接类),这时就需要限制该类可以实例化多个对象(仅仅能实例化一个对象),可以节省开销(如内存,运行时间),这种设计称之为单例模式(也称为数据库模式,因为使用这个模式的最多的地方一般就是数据库)。

三私一公的类内实现单例设计

class MySQLDB{
    private function __construct(){}
    private static $_job;
    private function __clone(){}
    public static function getMysqlJob(){
        if(!isset(static::$_job)){
            static::$_job==new static();
        }
        return static::$_job;
    }
}

构造方法使用的私有化(private)限制符,使用常规的new实例化时自动调用构造方法会报错,从而实例化失败

创建静态公共方法,在类内实例化该类,由于是在类内实例化,所以可以访问构造方法,实例化会成功:$MySQLDB=MySQLDB::getMysqlJob();

定义私有的静态变量$_job,而getMysqlJob()函数中会判断$_job的值是否为NULL(即没有实例化过),如果$_job已经存在一个对象,那么不实例化该类直接返回$_job的对象,这样多次实例化也只会实例化一个对象。

克隆方法使用私有化限制符来防止对象克隆导致多个对象的产生。

类外实现单例模式的效果(并不是严格意义上的单例模式,仅仅是实现了效果):

function getJob($class_name){
    static $job_list=array();
    if(!isset($job_list[$class_name])){
        $job_list[$class_name]==new $class_name();
    }
    return $job_list[$class_name];
}

这种方法并没有从根本上解决单例问题(仍然可以使用new来实例化多个对象),但是优势很明显,比较灵活,不需要改变类本身,同时能适用多个类。

但是这个是面向过程,我们使用面向对象开发的时候虽然这样能实现单例的效果,但是一般不使用这样的方式,而使用工厂模式。

工厂模式:

从类的功能上讲,如果某个类的主要功能就是用来生产其他类的对象,这样的类称之为工厂类。由于工厂类一般情况下不需要自身实例化对象,所以一般工厂类的成员都设置为静态成员,所以工厂类又被称为静态工厂。

class Factory{
    public static function getJob($class_name){
        static $job_list=array();
        if(!isset($job_list[$class_name])){
            $job_list[$class_name]==new $class_name();
        }
            return $job_list[$class_name];
    }
}

仅仅通过new去实例化对象,有时候不能满足某些实际的业务逻辑,比如说单例模式,所以需要工厂。

类型约束:

约束函数或方法的参数的数据类型的一种语法

class Ajob{ public function fun01(Bjob $job){} }

上面例子中Ajob类中的方法fun01的参数前面加了Bjob限制条件,表示该方法调用时传入的参数$job必须是Bjob类或Bjob类的子类所实例化的对象,传入其他会报错。

注意点:

class Ajob{ public function fun01(String $job){} }

上面例子中的方法在调用时并不是标识限制$job为字符串类型,php会寻找名称为Srting的类,如果该类存在(该类存在与php内核中),那么检测$job是否是该类的一个实例对象,而此时传入参数如果为字符串那么由于字符串并不是对象,会报错,int、bool等数据类型同理。

但是目前比较新的php版本中有一个特例(比较旧的版本没有这个特例),就是数组类型array,当限制条件为array时php会检测传入参数是否是数组类型。

最后编辑:
作者:qingheluo
这个作者貌似有点懒,什么都没有留下。