PHP和golang实现设计模式-单例模式

单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例类的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。

PHP实现:

<?php  

class Singleton {  
    //保存类实例的静态成员变量  
    private static $_instance;  

    //private 构造函数  
    private function __construct() {  
    }  

    private function __clone() {  
    }  

    //单例方法访问类实例  
    public static function getInstance() {  
        if (!(self::$_instance instanceof self)) {  
            self::$_instance = new self();  
        }  
        return self::$_instance;  
    }  
}  

$instance = Singleton::getInstance();

将构造方法设为private从而防止直接new一个对象;将__clone方法设为private,防止通过clone复制一个对象;需要该类对象”只能”通过调用Singleton::getInstance()方法的方式,而getInstance方法通过”饿汉模式”保证类变量$_instance只会被初始化一次,即Singleton类只能有一个对象。
一般来说我们平时大多都这么写的,没太大问题,但是会有一些情况下通过反射创建对象,序列化反序列化后创建的对象,多线程创建的对象会破坏上述单例模式。详细请看这篇文章的分析http://blog.csdn.net/yesuhuangsi/article/details/52187875

golang实现:

package Singleton

type singleton struct {
}

var instance *singleton

func GetInstance() *singleton {
    if instance == nil {
        instance = &singleton{}
    }
    return instance
}

同样的饿汉模式实现单例,这在go里面同样非线程安全,不能在多线程中正常工作,我们可以给它带上线程锁:

package Singleton

import (
    "sync"
)

type singleton struct {
}

var (
    instance *singleton
    mu       sync.Mutex
)

func GetInstance() *singleton {
    if instance == nil {
        mu.Lock()
        defer mu.Unlock()
        if instance == nil{
            instance = &singleton{}
        }
    }
    return instance
}

sync.mutext是Go语言底层基础对象之一,用于构建多个goroutine间的同步逻辑,因此被大量高层对象所使用。
这是一个不错的方法,但是还并不是很完美。因为编译器优化没有检查实例存储状态。如果使用sync/atomic包的话 就可以自动帮我们加载和设置标记。

package Singleton

import (
    "sync"
    "sync/atomic"
)

type singleton struct {
}

var (
    instance    *singleton
    mu          sync.Mutex
    initialized uint32
)

func GetInstance() *singleton {
    if atomic.LoadUInt32(&initialized) == 1 {
        return instance
    }

    mu.Lock()
    defer mu.Unlock()

    if initialized == 0 {
        instance = &singleton{}
        atomic.StoreUint32(&initialized, 1)
    }

    return instance
}

还有一种简洁的方式非常好

package singleton

import (
    "sync"
)

type singleton struct {
}

var instance *singleton
var once sync.Once

func GetInstance() *singleton {
    once.Do(func() {
        instance = &singleton{}
    })
    return instance
}

利用了once.Do(f)只执行一次的特性。
参考了文章:https://xiequan.info/go%E7%9A%84%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值