当前位置:首页 > 设计模式 > 正文内容

单例模式(Singleton)和 多例模式(Multiton)

phpmianshi9年前 (2012-04-09)设计模式239

1、概念

简单说来,单例模式的作用就是保证在整个应用程序的生命周期中,任何一个时刻,单例类的实例都只存在一个,同时这个类还必须提供一个访问该类的全局访问点。 常见使用实例:数据库连接器;日志记录器(如果有多种用途使用多例模式);锁定文件。

2、示例

Singleton.php

<?php

/**
 * Singleton类
 */
class Singleton
{
    private static $instance;
    
    /**
     * 通过延迟加载(用到时才加载)获取实例
     *
     * @return self
     */
    public static function getInstance()
    {
        if (null === static::$instance) {
            static::$instance = new static;
        }

        return static::$instance;
    }

    /**
     * 构造函数私有,不允许在外部实例化
     *
     */
    private function __construct()
    {
    }

    /**
     * 防止对象实例被克隆
     *
     * @return void
     */
    private function __clone()
    {
    }

    /**
     * 防止被反序列化
     *
     * @return void
     */
    private function __wakeup()
    {
    }
}


3、如何避免子类继承时,会重写构造方法或者clone方法

只需要在构造方法和clone方法前面加上final即可

方法前加final,可防止方法被覆盖,类前面加final可防止被继承


下面比较一下懒汉式和饿汉式:

懒汉式:默认不会实例化,什么时候用什么时候new。

饿汉式:类加载的时候就实例化,并且创建单例对象。

 懒汉式和饿汉式区别:

实例化方面:懒汉式默认不会实例化,外部什么时候调用什么时候new。饿汉式在类加载的时候就实例化,并且创建单例对象。

线程安全方面:饿汉式线程安全 (在线程还没出现之前就已经实例化了,因此饿汉式线程一定是安全的)。懒汉式线程不安全( 因为懒汉式加载是在使用时才会去new 实例的,那么你去new的时候是一个动态的过程,是放到方法中实现的,比如:

public static synchronized Lazy getInstance(){   
    if(lazy==null){  
        lazy=new Lazy(); 
    } 
}

如果这个时候有多个线程访问这个实例,这个时候实例还不存在,还在new,就会进入到方法中,有多少线程就会new出多少个实例。一个方法只能return一个实例,那最终return出哪个呢?是不是会覆盖很多new的实例?这种情况当然也可以解决,那就是加同步锁,避免这种情况发生) 。

执行效率上:饿汉式没有加任何的锁,因此执行效率比较高。懒汉式一般使用都会加同步锁,效率比饿汉式差。

性能上:饿汉式在类加载的时候就初始化,不管你是否使用,它都实例化了,所以会占据空间,浪费内存。懒汉式什么时候需要什么时候实例化,相对来说不浪费内存。

4、多例模式

Multiton与singleton相似,不同的是后者需要getInstance()函数传递关键值。

多例模式被公认为是 反面模式(在软件工程中,一个反面模式(Anti-pattern 或 Antipattern)指的是在实践中明显出现但又低效或是有待优化的设计模式,是用来解决问题的带有共同性的不良方法。它们已经经过研究并分类,以防止日后重蹈覆辙,并能在研发尚未投产的系统时辨认出来),为了获得更好的可测试性和可维护性,请使用『依赖注入模式』。

Multiton节省内存,并确保同一个对象的多个实例不发生冲突.


使用场景:

  • 2 个数据库连接器,比如一个是 MySQL ,另一个是 SQLite

  • 多个记录器(一个用于记录调试消息,一个用于记录错误)

<?php 
class MultitonExample{ 

    private function __construct(){}//防止直接实例化 

    public static function getInstance($key){ 
 
        static $instance=array();    
 
        if(!array_key_exists($key,$instance)){ 
             $instance[$key]=new SingletonExample(); 
        }
        return $instance($key);
    }
 };
 ?>


版权声明:本文由PHP面试资料网发布,如需转载请注明出处。
分享给朋友:

相关文章

php中享元模式

概念享元模式(Flyweight),为了节约内存的使用,享元模式会尽量使类似的对象共享内存。在大量类似对象被使用的情况中这是十分必要的。常用做法是在外部数据结构中保存类似对象的状态,并在需要时将他们传...

php中的模板模式

概念在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。定义一个操作中的算法的骨架,而将一...

php中装饰器模式

概念装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。这种模式创建了一个装饰类,用来包...

php中的适配器模式

概念适配器模式(Adapter)模式:将一个类的接口,转换成客户期望的另一个类的接口。适配器让原本接口不兼容的类可以合作无间。场景老代码接口不适应新的接口需求,或者代码很多很乱不便于继续修改,或者使用...

php中策略模式详解

概念在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。场景场景1:假设现在要设计一个购物车系统,一个最简单的情况就是把所有货品的...

Laravel中用到的设计模式

1:工厂模式Auth::user()此处Auth这个类就是工厂中的方法,Auth是注册树中的别名。好处:类似于函数的封装,使对象有一个统一的生成(实例化)入口。当我们对象所对应的类的类名发生变化的时候...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。