关于单例模式:单例设计模式的优缺点

在软件工程中,设计模式是一种在软件设计中经常出现问题的解决方案。它不是能够间接转化成代码的模板,而是在特定状况下能够利用的一套规定或概念。设计模式能够减速开发过程,通过提供通过测试和证实的开发范式来缩小前期可能呈现的问题和谬误。 在面向对象编程(OOP)畛域中,设计模式被广泛应用,以解决常见的软件设计问题。其中,单例(Singleton)模式是一种十分独特且宽泛应用的设计模式。它的外围目标是确保一个类只有一个实例,并提供一个全局拜访点来获取这个实例。 单例(Singleton)模式的定义单例模式确保了一个类只有一个实例存在,同时提供了一个全局拜访点来获取这个实例。在很多状况下,确保某个类在整个零碎中只有一个实例十分重要,比方配置管理器、线程池、缓存或者日志对象等。应用单例模式能够防止因为多个实例造成的资源应用抵触,或是数据不统一的问题。 实现单例模式实现单例模式通常波及以下几个关键步骤: 私有化构造函数:确保内部代码不能通过结构器创立类的实例。提供一个公有的动态变量:用于保留类的惟一实例。提供一个私有的静态方法:这个办法返回上述动态变量指向的实例。如果实例不存在,该办法会先创立它,而后返回。单例模式的 Java 实现以下是一个简略的单例模式的 Java 实现示例: public class Singleton { // 1. 创立一个公有的动态变量,用于保留单例实例,初始时为 null private static Singleton instance = null; // 2. 私有化构造函数,避免内部通过 new 创立实例 private Singleton() {} // 3. 提供一个私有的静态方法,返回单例实例 public static Singleton getInstance() { if (instance == null) { // 如果实例不存在,进入同步区块 synchronized (Singleton.class) { // 再次查看实例是否存在,防止多线程问题 if (instance == null) { instance = new Singleton(); } } } return instance; }}在这个例子中,Singleton 类通过私有化其构造函数避免内部通过 new 关键字创立实例。它应用一个名为 instance 的公有动态变量来持有类的惟一实例,并提供一个私有的静态方法 getInstance() 来让内部获取这个实例。这个办法首先查看 instance 是否曾经被创立,如果没有,则创立它。为了确保在多线程环境下这个类仍旧只有一个实例,应用了同步块。 ...

March 1, 2024 · 1 min · jiezi

关于单例模式:多线程环境单例模式

多线程环境单例模式 : 双重检测+上锁public class Singleton {/** * 结构器私有化避免被公共创立 */private Singleton() { }//创立多线程锁private static Object lock = new Object();//单例本体private static Singleton singleton = null;//获取单例public static Singleton getInstance() { //当多线程环境中单例本体为空 if (singleton == null) { //上锁避免被其余线程争夺 synchronized (lock) { //双重查看更加平安和合乎业务场景 if (singleton == null) { //加锁和双重检测后初始化单例 singleton = new Singleton(); } } } //返回单例后果 return singleton; }}

February 22, 2022 · 1 min · jiezi

关于单例模式:C11单例模式线程安全

单例模式留神:单例模式会让程序变得难以测试,所以尽可能不要应用单实例模式。保障一个类只有一个实例,并且提供了拜访该实例的全局拜访点。 线程平安的单例模式-C++11Singleton.h#pragma oncetemplate<typename T>class Singleton{public:    static T& instance() {        static T instance{ token{} };        return instance;   }    Singleton(const Singleton&) = delete;    Singleton& operator= (const Singleton) = delete;protected:    struct token {};    Singleton() {}};Example#include <Singleton.h>#include <iostream>class Test final : public Singleton<Test>{public:    Test(token) { std::cout << "constructed" << std::endl; }    ~Test() {  std::cout << "destructed" << std::endl; }    void use() const { std::cout << "in use" << std::endl; };};int main(){    // Test cannot_create; /* ERROR */    std::cout << "Entering main()" << std::endl;   {        auto const& t = Test::instance();        t.use();   }   {        auto const& t = Test::instance();        t.use();   }    std::cout << "Leaving main()" << std::endl;}隐患如果单例类位于 dll 库中,是否还能保障惟一? ...

December 11, 2021 · 1 min · jiezi

关于单例模式:DCL

DCL 单例模式DCL 就是 Double Check Lock 的缩写,即双重查看的同步锁。代码如下, public class Singleton { // volatile避免指令重排 private static volatile Singleton singleton = null; private Singleton(){ } public static Singleton getInstance(){ //进入办法内,先判断实例是否为空,以确定是否须要进入同步代码块 if(singleton == null){ synchronized (Singleton.class){ //进入同步代码块时再次判断实例是否为空 if(singleton == null){ singleton = new Singleton(); } } } return singleton; }}DCL 单例线程平安问题失常状况,能够保障调用 getInstance 办法两次,拿到的是同一个对象。然而,Java 中有个很弱小的性能——反射通过反射,就能够毁坏单例模式,从而调用它的构造函数,来创立不同的对象。 通过 反射 拿对象的hashcode public static void main(String[] args) throws Exception { Singleton singleton1 = Singleton.getInstance(); System.out.println(singleton1.hashCode()); Class<Singleton> clazz = Singleton.class; Constructor<Singleton> ctr = clazz.getDeclaredConstructor(); ctr.setAccessible(true); Singleton singleton2 = ctr.newInstance(); System.out.println(singleton2.hashCode()); }打印后果如下: ...

May 11, 2021 · 2 min · jiezi

关于单例模式:单例模式

什么是单例模式?保障一个类只有一个实例,并提供一个全局变量来拜访这个实例,这就是单例模式,单例模式属于对象创立型模式。 单例模式的几个因素类只能有一个实例这个实例必须由该类自身创立该类必须向整个零碎提供该实例的拜访权限单例模式的构造 单例模式的实现class Singleton{ private static Singleton s_Instance; //公有构造方法,避免内部实例化 private Singleton() { } public static Singleton GetInstance() { if (s_Instance == null) s_Instance = new Singleton(); return s_Instance; }}测试代码 static void Main(){ var s1 = Singleton.GetInstance(); var s2 = Singleton.GetInstance(); if (object.ReferenceEquals(s1, s2)) Console.WriteLine($"s1 s2两个实例是雷同的"); Console.ReadKey();}后果 饿汉式单例与懒汉式单例饿汉式单例(最简略的单例) class EagerSingleton{ //类加载时执行 private static EagerSingleton s_Instance = new EagerSingleton(); private EagerSingleton() { } public static EagerSingleton GetInstance() { return s_Instance; }}懒汉式单例//懒汉式单例与饿汉式单例不同的在于:懒汉式单例在第一次被援用时将本人实例化(类被加载时不会实例化本身)class LazySingleton{ private static LazySingleton s_Instance; //公有构造方法,避免内部实例化 private LazySingleton() { } public static LazySingleton GetInstance() { if (s_Instance == null) s_Instance = new LazySingleton(); return s_Instance; }}懒汉式单例的线程平安问题在高并发多线程的环境下运行懒汉式单例的代码,会呈现在某一时刻存在多个线程同时拜访GetInstance办法,可能会创立多个实例,违反了单例模式的设计用意。 ...

May 10, 2021 · 1 min · jiezi

关于单例模式:设计模式之单例模式

单例模式单例模式(Singleton Pattern)是 Java 中最简略的设计模式之一。这种类型的设计模式属于创立型模式,它提供了一种创建对象的最佳形式。 这种模式波及到一个繁多的类,该类负责创立本人的对象,同时确保只有单个对象被创立。这个类提供了一种拜访其惟一的对象的形式,能够间接拜访,不须要实例化该类的对象。‘’ 留神: 1、单例类只能有一个实例。2、单例类必须本人创立本人的惟一实例。3、单例类必须给所有其余对象提供这一实例。介绍用意:保障一个类仅有一个实例,并提供一个拜访它的全局拜访点。 次要解决:一个全局应用的类频繁地创立与销毁。 何时应用:当您想管制实例数目,节俭系统资源的时候。 如何解决:判断零碎是否曾经有这个单例,如果有则返回,如果没有则创立。 要害代码:构造函数是公有的。 利用实例: 1、一个班级只有一个班主任。2、Windows 是多过程多线程的,在操作一个文件的时候,就不可避免地呈现多个过程或线程同时操作一个文件的景象,所以所有文件的解决必须通过惟一的实例来进行。3、一些设施管理器经常设计为单例模式,比方一个电脑有两台打印机,在输入的时候就要解决不能两台打印机打印同一个文件。长处: 1、在内存里只有一个实例,缩小了内存的开销,尤其是频繁的创立和销毁实例(比方治理学院首页页面缓存)。2、防止对资源的多重占用(比方写文件操作)。毛病:没有接口,不能继承,与繁多职责准则抵触,一个类应该只关怀外部逻辑,而不关怀里面怎么样来实例化。 应用场景: 1、要求生产惟一序列号。2、WEB 中的计数器,不必每次刷新都在数据库里加一次,用单例先缓存起来。3、创立的一个对象须要耗费的资源过多,比方 I/O 与数据库的连贯等。注意事项:getInstance() 办法中须要应用同步锁 synchronized (Singleton.class) 避免多线程同时进入造成 instance 被屡次实例化。 实现咱们将创立一个 SingleObject 类。_SingleObject_ 类有它的公有构造函数和自身的一个动态实例。 SingleObject 类提供了一个静态方法,供外界获取它的动态实例。_SingletonPatternDemo_ 类应用 SingleObject 类来获取 SingleObject 对象。 步骤 1创立一个 Singleton 类。 SingleObject.javapublic class SingleObject { //创立 SingleObject 的一个对象 private static SingleObject instance = new SingleObject(); //让构造函数为 private,这样该类就不会被实例化 private SingleObject(){} //获取惟一可用的对象 public static SingleObject getInstance(){ return instance; } public void showMessage(){ System.out.println("Hello World!"); }}步骤 2从 singleton 类获取惟一的对象。 ...

November 14, 2020 · 2 min · jiezi

关于单例模式:C单例模式实现

最不便罕用的是Meyers' Singleton,多线程平安。gcc 4.0之后的编译器反对这种写法,要求C++11及其当前的版本。 class Singleton{public: // 留神返回的是援用 static Singleton &getInstance() { static Singleton instance; // 动态局部变量 return instance; }private: Singleton() = default; Singleton(const Singleton &) = delete; // 禁用拷贝构造函数 Singleton &operator=(const Singleton &) = delete; // 禁用拷贝赋值运算符};残缺的验证程序: #include <iostream>using namespace std;class Singleton{public: // 留神返回的是援用 static Singleton &getInstance() { static Singleton instance; // 动态局部变量 return instance; }private: Singleton() = default; Singleton(const Singleton &) = delete; // 禁用拷贝构造函数 Singleton &operator=(const Singleton &) = delete; // 禁用拷贝赋值运算符};int main(){ Singleton& s1 = Singleton::getInstance(); // &是援用 cout << &s1 << endl; // &是取地址 Singleton& s2 = Singleton::getInstance(); cout << &s2 << endl; // Singleton s3(s1); // s2 = s1; system("pause"); return 0;}打印出s1和s2的地址是同一个,因为是同一个动态局部变量。 ...

October 10, 2020 · 1 min · jiezi