【Go实现】实践GoF的23种设计模式:单例模式
在Go语言中,我们实践GoF设计模式中的单例模式,它的核心理念是确保一个类仅有一个实例并提供全局访问。当需要像线程池、全局缓存这样的全局唯一对象时,单例模式就显得尤为合适,因为它可以限制创建实例,且便于在全局点进行功能扩展。然而,并非所有场景都适用单例。例如,统计API调用次数时,如果创建多个单例(如SuccessApiMetric和FailApiMetric),随着指标增加,代码会变得冗余。更好的做法是将指标封装在单个对象ApiMetric下的实例中。判断是否使用单例,关键在于对象是否具备“中心点”角色,如管理所有线程的线程池。Go语言中实现单例模式略有不同,利用包的访问规则模拟私有构造函数和静态方法。在分布式应用系统的示例中,我们以network模块为例,它是中心节点,因此采用单例模式。有“饿汉模式”和“懒汉模式”,前者在初始化时实例化,后者延迟至使用时,以节省内存。尽管单例模式强调一个实例,但设计时还需考虑灵活性,如网络模块可能需要区分互联网和局域网,此时可以为每个子网络创建不同的实例
【Go实现】实践GoF的23种设计模式:单例模式
GoF的23种设计模式之一:单例模式,其核心在于确保一个类只有一个实例,并提供全局访问点。在需要共享资源且仅需一个实例的场景,如线程池、全局缓存等,单例模式显得尤为合适。然而,过度使用单例可能导致代码冗余和设计不当。例如,统计API调用指标时,如果将每个指标都设计为单例,会随着指标增多而变得复杂。正确的做法是根据中心点原则,将相关指标组合成一个对象内的实例,而非多个单例。在Go中,实现单例并非直接模仿C++/Java的构造函数和静态方法,而是利用package访问规则。Go的network模块作为中心点,自然地采用单例模式。单例模式分为“饿汉模式”(初始化时创建)和“懒汉模式”(延迟初始化),后者需考虑线程安全问题。尽管单例模式强调限制实例化,但在某些场景下,可以考虑提供多个实例,或者通过抽象接口实现多态,以适应未来可能的扩展。但要注意,单例模式的滥用可能导致全局变量的问题,如代码耦合和扩展困难
实例变量(全局变量)
实例变量声明在一个类中,但在方法、构造方法和语句块之外实例变量具有默认值。数值型变量的默认值是0,布尔型变量的默认值是false,引用类型变量的默认值是null。变量的值可以在声明时指定,也可以在构造方法中指定;实例变量可以直接通过变量名访问。但在静态方法以及其他类中,就应该使用完全限定名:ObejectReference.VariableName。 当一个对象被实例化之后,每个实例变量的值就跟着确定。实例变量在对象创建的时候创建,在对象被销毁的时候销毁。如果调用某个对象的某个方法去改变实例变量多次,那么这个实例变量的值就是多次改变的结果。 小测试: 输出结果: 实例变量属于类对象的,也就是说,属于对象实例私有,在虚拟机的堆中分配。 实例变量是实例对象私有的,系统只存在一个实例对象,则在多线程环境下,如果值改变后,则其它对象均可见,故线程非安全;如果每个线程都在不同的实例对象中执行,则对象与对象间的修改互不影响,故线程安全
单例和全局变量的区别
1、单例的特点: 保证某类只存在唯一实例。 该类本身完成自身的初始化。 获取该唯一实例的方式非常明确,可以通过该类本身定义的静态方法getInstance()获取该类的唯一实例引用。 2、静态变量定义某类的实例引用特点: 该类的实例引用的静态变量...
C++关于DLL中使用全局变量造成内存泄露的问题,不要说为什么不改用成员变量之类的话
即便是全局变量,如果是一般变量或是结构体,也不会有内存泄露的问题. 出现内存泄露,应该全局变量是指针,在需要的时候new了,但是不知道什么时候delete. 比较典型的就是单例模式instance* GetInstance(){if(!pInstance) { pInstance = new instance; return pInstance;}}如果真的没有合适的地方去delete这个全局变量你可以试一下onExit函数,以前用过,暂时想不起来,要查一下.