设计模式_五种单例模式

五种单例实现:

(1)饿汉模式:(线程安全,调用率高,但是不能延时加载)
      public class Singleton1{

           //类初始化时就立即加载对象(没有延迟加载的优势),天然的线程安全。
           private static Singleton1 singleton1 = new Singleton1();
           private Singleton1() {
               //构造方法私有化
           }
           //方法没有同步,调用效率高
           public static Singleton1 getInstance(){
               return singleton1;
           }
       }   
(2)懒汉模式:(线程安全,调用率不高,但是可以延时加载)
       public class Singleton2{
            private static Singleton2 singleton2;
            private Singleton2(){
                //构造方法私有化
            }
            public synchronized static Singleton2 getInstance2(){
                if(singleton2 == null){
                    singleton2 = new Singleton2();
                }
                return singleton2();
            }
        }
(3)双重检测锁模式:(由于JVM底层模型问题,偶尔会出问题,不建议使用)
        public class Singleton3{
            private volatile static Singleton3 singleton3;
            private Singleton3(){
                //构造私有化
            }
            public static Singleton3 getInstance3(){
                if(singleton3 == null){
                    synchronized (Singleton3.class){
                        if(singleton3 == null){
                            singleton3 = new Singleton3();
                        }
                    }
                }
                return singleton3;
            }
        }
(4)静态内部类模式:(线程安全,调用率高,可以延时加载)
  • 通过内部类机制使得单例对象可以延迟加载,同时内部类相当于是外部类的静态部分,所以可以通过JVM来保证线程安全
      public class Singleton4{
            private static class Singleton4Holder{
                private static Singleton4 singleton4 = new Singleton4();
            }
            private Singleton4(){
                //构造私有化
            }
            public static Singleton4 getInstance(){
                return Singleton4Holder.singleton4;
            }

        }
(5)枚举模式:(线程安全,调用率高,不能延时加载,但是可以天然防止反射和反序列化调用)
    public enum Singleton5{
            singleton5
    }
}
<think>好的,用户想知道如何用Python中的__call__方法实现单例模式。首先,我需要回忆下单例模式的基本概念,确保自己理解正确。单例模式确保一个类只有一个实例,并提供全局访问点。通常实现方式可能有使用模块、装饰器、元类或者重写__new__方法。 用户提到使用__call__方法,这通常和元类相关。因为当创建类实例时,如果元类定义了__call__,它会覆盖默认的实例创建过程。所以可能需要通过自定义元类,在__call__方法中控制实例的生成次数。 接下来,我需要确认__call__在元类中的作用。元类的__call__方法会在创建类实例时被调用,比如当执行MyClass()时,实际上是调用了元类的__call__方法。因此,在元类的__call__中,可以判断是否已经存在实例,如果没有则创建,否则返回已有的实例。 然后,需要编写示例代码。首先定义一个元类SingletonType,重写它的__call__方法。在__call__中检查类是否有_instance属性,如果没有,则调用父类的__call__方法创建实例,并保存到_instance中。之后每次调用都返回这个_instance。 另外,可能需要考虑线程安全的问题。但在Python中,如果只是简单的单例,可能不需要处理复杂的线程同步,但用户如果没有特别提到,可能暂时忽略这一点,或者简单提及。 然后,给出一个使用该元类的示例类,比如class MyClass(metaclass=SingletonType),并演示创建实例后,两个实例是否相同。 需要检查代码是否正确,确保元类的使用在Python3中是有效的语法,因为Python2和3的元类声明方式不同,这里用户应该使用的是Python3。 另外,可能还需要对比其他实现方式,比如使用__new__方法,或者装饰器,说明使用__call__的优点或不同之处。比如,使用元类的方式更隐式,不需要每次在类中重写__new__,而是通过元类统一管理。 最后,确保回答结构清晰,分步骤说明,让用户能够理解每一步的作用,以及为什么这样做可以实现单例模式。同时,提醒可能需要注意的问题,比如子类化时的行为,或者多线程环境下的考虑,但根据用户的问题,可能不需要深入展开,除非用户进一步询问。 总结步骤:1. 解释单例模式;2. 引入元类的概念;3. 说明__call__方法在元类中的作用;4. 编写示例代码;5. 测试代码有效性;6. 对比其他实现方式的差异;7. 指出潜在注意事项。</think>可以通过元类重写`__call__`方法实现单例模式,具体步骤如下: ### 一、单例模式核心原理 单例模式要求一个类**只能创建一个实例**。关键点在于: 1. 拦截实例创建过程 2. 在首次调用时创建实例 3. 后续调用直接返回已创建实例 ### 二、实现代码 ```python class SingletonType(type): _instances = {} # 存储所有单例类实例的字典 def __call__(cls, *args, **kwargs): # 检查是否已有该类的实例 if cls not in cls._instances: # 调用父类type的__call__创建实例 cls._instances[cls] = super().__call__(*args, **kwargs) return cls._instances[cls] class MyClass(metaclass=SingletonType): def __init__(self, value): self.value = value # 测试代码 a = MyClass(10) b = MyClass(20) print(a is b) # 输出:True print(a.value) # 输出:10(第二个参数20被忽略) ``` ### 三、实现解析 1. **元类工作机制**: - 当通过`MyClass()`创建实例时 - 实际调用的是其元类`SingletonType`的`__call__`方法 2. **执行流程**: ```mermaid graph TD A[MyClass()] --> B{检查_instances字典} B -->|不存在| C[调用type.__call__创建实例] B -->|已存在| D[返回已有实例] C --> E[存入_instances字典] ``` 3. **字典存储设计**: - 使用类变量`_instances`存储所有单例类实例 - 键为类对象,值为对应实例 - 支持多个类同时使用该单例方案 ### 四、对比其他实现方式 | 实现方式 | 优点 | 缺点 | |----------------|--------------------------|--------------------------| | 元类`__call__` | 自动继承,无需修改子类代码 | 需要理解元类机制 | | 重写`__new__` | 实现简单 | 每个类都需要单独实现 | | 装饰器 | 非侵入式 | 无法通过继承实现单例特性 | ### 五、注意事项 1. **线程安全**:在多线程环境下需加锁 ```python from threading import Lock class SingletonType(type): _instances = {} _lock = Lock() def __call__(cls, *args, **kwargs): with cls._lock: if cls not in cls._instances: cls._instances[cls] = super().__call__(*args, **kwargs) return cls._instances[cls] ``` 2. **子类化问题**:子类默认继承父类的元类,但每个子类会有独立的单例实例 3. **实例重置**:如需重新创建实例,可添加清除方法 ```python class SingletonType(type): # ... 其他代码同前 ... def clear_instance(cls): if cls in cls._instances: del cls._instances[cls] ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值