Singleton设计模式
单例设计模式优缺点及使用场景
单例设计模式优缺点及使⽤场景单利模式的优缺点和使⽤场景⾸先介绍⼀下单例模式:单例模式(Singleton),也叫单⼦模式,是⼀种常⽤的软件设计模式。
在应⽤这个模式时,单例对象的类必须保证只有⼀个实例存在。
许多时候整个系统只需要拥有⼀个的全局对象,这样有利于我们协调系统整体的⾏为。
⽐如在某个服务器程序中,该服务器的配置信息存放在⼀个⽂件中,这些配置数据由⼀个单例对象统⼀读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息。
这种⽅式简化了在复杂环境下的配置管理。
实现单例模式的思路是:⼀个类能返回对象⼀个引⽤(永远是同⼀个)和⼀个获得该实例的⽅法(必须是静态⽅法,通常使⽤getInstance这个名称);当我们调⽤这个⽅法时,如果类持有的引⽤不为空就返回这个引⽤,如果类保持的引⽤为空就创建该类的实例并将实例的引⽤赋予该类保持的引⽤;同时我们还将该类的构造函数定义为私有⽅法,这样其他处的代码就⽆法通过调⽤该类的构造函数来实例化该类的对象,只有通过该类提供的静态⽅法来得到该类的唯⼀实例。
需要注意的地⽅:单例模式在多线程的应⽤场合下必须⼩⼼使⽤。
如果当唯⼀实例尚未创建时,有两个线程同时调⽤创建⽅法,那么它们同时没有检测到唯⼀实例的存在,从⽽同时各⾃创建了⼀个实例,这样就有两个实例被构造出来,从⽽违反了单例模式中实例唯⼀的原则。
解决这个问题的办法是为指⽰类是否已经实例化的变量提供⼀个互斥锁(虽然这样会降低效率)。
优点:1.在单例模式中,活动的单例只有⼀个实例,对单例类的所有实例化得到的都是相同的⼀个实例。
这样就防⽌其它对象对⾃⼰的实例化,确保所有的对象都访问⼀个实例2.单例模式具有⼀定的伸缩性,类⾃⼰来控制实例化进程,类就在改变实例化进程上有相应的伸缩性。
3.提供了对唯⼀实例的受控访问。
4.由于在系统内存中只存在⼀个对象,因此可以节约系统资源,当需要频繁创建和销毁的对象时单例模式⽆疑可以提⾼系统的性能。
写一个简单的单例模式
单例模式单例模式(Singleton Pattern)是Java中最简单的设计模式之一。
这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。
这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
注意:•1、单例类只能有一个实例。
•2、单例类必须自己创建自己的唯一实例。
•3、单例类必须给所有其他对象提供这一实例。
介绍意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
主要解决:一个全局使用的类频繁地创建与销毁。
何时使用:当您想控制实例数目,节省系统资源的时候。
如何解决:判断系统是否已经有这个单例,如果有则返回,如果没有则创建。
关键代码:构造函数是私有的。
应用实例:1、一个党只能有一个主席。
2、Windows是多进程多线程的,在操作一个文件的时候,就不可避免地出现多个进程或线程同时操作一个文件的现象,所以所有文件的处理必须通过唯一的实例来进行。
3、一些设备管理器常常设计为单例模式,比如一个电脑有两台打印机,在输出的时候就要处理不能两台打印机打印同一个文件。
优点:1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。
2、避免对资源的多重占用(比如写文件操作)。
缺点:没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。
使用场景:1、要求生产唯一序列号。
2、WEB中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。
3、创建的一个对象需要消耗的资源过多,比如I/O与数据库的连接等。
注意事项:getInstance()方法中需要使用同步锁synchronized (Singleton.class)防止多线程同时进入造成instance被多次实例化。
实现我们将创建一个SingleObject类。
Singleton模式在软件开发中的应用分析与实战应用
Singleton模式在软件开发中的应用分析与实战应用Singleton模式是一种应用广泛的设计模式,其目的是确保一个类在程序中只有一个实例,并提供一个全局访问点。
Singleton模式在软件开发中的应用非常广泛,今天我们就来分析一下其具体的应用场景以及实战应用。
一、Singleton模式的应用场景1.资源共享很多时候,在程序中需要同步访问某些资源,例如配置文件、数据库连接等,如果没有Singleton模式,每个线程或者每个对象都会创建自己的实例,这样会导致资源的浪费和不必要的性能开销。
而Singleton模式可以保证在整个程序中只有一个实例,所有线程或对象共享这个实例,从而避免了资源的浪费和性能开销。
2.线程池线程池是一种复用线程的技术,有时需要在回收到线程池中的线程之前,对线程中的变量或状态进行一些清理或初始化工作。
Singleton模式可以将这些线程清理或初始化的操作统一到一个全局访问点,以确保每个线程在回收到线程池中之前都能完成必要的清理或初始化工作。
3.日志系统日志系统是每个软件开发项目中必不可少的一部分,可以通过Singleton模式来保证日志系统在整个程序中只有一个实例,从而方便对日志输出方式的控制和管理。
二、Singleton模式的实战应用1.数据库连接池数据库连接池是应用Singleton模式的一个经典场景,其目的是确保在程序中只有一个数据库连接实例,所有访问数据库的线程都使用这个实例。
这不仅可以避免资源的浪费和性能开销,还可以有效地控制数据库连接的数量,从而提高系统的稳定性和效率。
2.日志系统日志系统是应用Singleton模式的另一个重要场景,其目的是确保在程序中只有一个日志实例,所有输出日志的对象都使用这个实例。
这样可以方便对日志输出方式的控制和管理,例如控制日志的级别、格式等。
3.配置文件管理器配置文件管理器是应用Singleton模式的另一个经典场景,其目的是确保在程序中只有一个配置文件管理器实例,所有访问配置文件的线程或对象都使用这个实例。
单例的构造函数和析构函数
单例的构造函数和析构函数单例模式是一种常用的设计模式,其目的是保证一个类只有一个实例,并提供一个全局访问点。
在实际开发中,我们经常需要使用单例模式来管理全局资源,例如日志、数据库连接等。
在本文中,我们将介绍单例模式的构造函数和析构函数的实现方法。
首先,我们需要了解什么是单例模式以及它的特点。
一、什么是单例模式单例模式(Singleton Pattern)是一种常用的软件设计模式。
它保证一个类只有一个实例,并提供一个全局访问点。
二、单例模式的特点1. 单例类只有一个实例对象;2. 该实例对象由单例类自行创建;3. 单例类必须向外界提供访问该实例对象的方法;4. 单例类可以有多个方法,这些方法操作该实例对象。
三、构造函数和析构函数1. 构造函数构造函数是一种特殊的成员函数,在创建对象时被调用。
它负责初始化对象的成员变量,并为对象分配内存空间。
在单例模式中,由于只有一个实例对象,因此需要对构造函数进行特殊处理。
下面是一个简单的示例代码:```class Singleton {private:static Singleton* instance;Singleton() {}public:static Singleton* getInstance() {if (instance == nullptr) {instance = new Singleton();}return instance;}};```在上面的代码中,我们定义了一个静态成员变量`instance`,并将构造函数设为私有。
这样就保证了只有单例类自己可以创建实例对象。
同时,我们定义了一个静态方法`getInstance()`,用于获取单例对象。
在该方法中,我们首先判断实例对象是否已经创建,如果没有,则创建一个新的实例对象并返回。
2. 析构函数析构函数是一种特殊的成员函数,在对象被销毁时被调用。
它负责释放对象占用的内存空间,并清理对象所持有的资源。
什么是Singleton?
什么是Singleton?Singleton:在Java中即指单例设计模式,它是软件开发中最常⽤的设计模式之⼀。
单:指唯⼀例:指实例单例设计模式,即某个类在整个系统中只能有⼀个实例对象可被获取和使⽤的代码模式。
要点:⼀、单例类只能有⼀个实例保证构造器私有化(防⽌通过构造器实例化)⼆、单例类必须⾃信创建这个实例在单例类中创建⼀个静态变量来保存这个唯⼀的实例三、单例类必须⾃⾏向整个系统提供这个实例对外提供该实例对象的获取⽅式1. 直接暴露该实例对象2. ⽤静态变量的get⽅法获取该实例对象单例的⼏种常见形式饿汉式:直接创建对象,不存在线程安全问题直接实例化饿汉式(简介直观)1/**2 * 单例饿汉式⼀(1)3 * 直接实例化饿汉式(简洁直观)4 * 对外提供获取该实例对象的⽅式:5 * (1)直接暴露6 * (2)⽤静态变量的get⽅法获取7*/8public class SingletonHungry1 {910public static final SingletonHungry1 INSTANCE = new SingletonHungry1();1112private SingletonHungry1() {}13 }141516/**17 * 单例饿汉式⼀(2)18 * 直接实例化饿汉式(简洁直观)19 * 对外提供获取该实例对象的⽅式:20 * (1)直接暴露21 * (2)⽤静态变量的get⽅法获取22*/23public class SingletonHungry2 {2425private static final SingletonHungry2 INSTANCE = new SingletonHungry2();2627private SingletonHungry2() {}2829public static SingletonHungry2 getInstance() {30return INSTANCE;31 }32 }枚举式(最简洁)1/**2 * 单例饿汉式⼆3 * 枚举式(最简洁)4*/5public enum SingletonHungry3 {6 INSTANCE7 }静态代码块饿汉式(适合复杂实例化)2 * 单例饿汉式三3 * 静态代码块饿汉式(适合复杂实例化)4*/5public class SingletonHungry4 {67public static final SingletonHungry4 INSTANCE;89private String info;1011static {12// 这⾥⽤来实现复杂的实例化13// ......复杂代码14try {15 Properties pro = new Properties();16 pro.load(SingletonHungry4.class.getClassLoader().getResourceAsStream("singleton.properties"));17 INSTANCE = new SingletonHungry4(pro.getProperty("info"));18 } catch (IOException e) {19throw new RuntimeException(e);20 }21 }2223private SingletonHungry4(String info) { = info;25 }26 }懒汉式:延迟创建对象线程不安全(适⽤于单线程)1/**2 * 单例懒汉式⼀3 * 线程不安全(适⽤于单线程)4*/5public class SingletonLazy1 {67private static SingletonLazy1 INSTANCE;89private SingletonLazy1() {}1011public static SingletonLazy1 getInstance() {12if (INSTANCE == null) {13try {14 Thread.sleep(100);15 } catch (InterruptedException e) {16 e.printStackTrace();17 }18 INSTANCE = new SingletonLazy1();19 }20return INSTANCE;21 }22 }线程安全(适⽤于多线程)1/**2 * 单例懒汉式⼆(1)3 * 线程安全(适⽤于多线程)4*/5public class SingletonLazy2 {67private static SingletonLazy2 INSTANCE;89private SingletonLazy2() {}1011public static SingletonLazy2 getInstance() {12synchronized (SingletonLazy2.class) {13if (INSTANCE == null) {14try {15 Thread.sleep(100);16 } catch (InterruptedException e) {17 e.printStackTrace();18 }19 INSTANCE = new SingletonLazy2();20 }21 }22return INSTANCE;23 }24 }2527 * 单例懒汉式⼆(2)28 * 线程安全(适⽤于多线程,优化效率)29*/30public class SingletonLazy3 {3132private static SingletonLazy3 INSTANCE;3334private SingletonLazy3() {}3536public static SingletonLazy3 getInstance() {37if (INSTANCE == null) { // 不等于空直接返回,提⾼效率38synchronized (SingletonLazy3.class) {39if (INSTANCE == null) {40try {41 Thread.sleep(100);42 } catch (InterruptedException e) {43 e.printStackTrace();44 }45 INSTANCE = new SingletonLazy3();46 }47 }48 }4950return INSTANCE;51 }52 }静态内部类形式(适⽤于多线程) 在内部类被加载和初始化时,才创建INSTANCE实例对象 静态内部类不会⾃动随着外部类的加载和初始化⽽初始化,它是要单独去加载和初始化的 因为是在内部类加载和初始化时创建的,因此是线程安全的1/**2 * 单例懒汉式三3 * 静态内部类(适⽤于多线程)4 * 在内部类被加载和初始化时,才创建INSTANCE实例对象5 * 静态内部类不会⾃动随着外部类的加载和初始化⽽初始化,它是要单独去加载和初始化的6 * 因为是在内部类加载和初始化时,创建的,因此是线程安全的7*/8public class SingletonLazy4 {910private SingletonLazy4() {}1112private static class Inner {13private static final SingletonLazy4 INSTANCE = new SingletonLazy4();14 }1516public static SingletonLazy4 getInstance() {17return Inner.INSTANCE;18 }19 }本⽂⽤于记录Singleton的学习,⽅便以后回顾!学完的东西容易忘,以⽂章的形式记录下来。
设计模式主要分三个类型
设计模式主要分三个类型:创建型、结构型和行为型。
其中创建型有:一、Singleton,单例模式:保证一个类只有一个实例,并提供一个访问它的全局访问点二、Abstract Factory,抽象工厂:提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们的具体类。
三、Factory Method,工厂方法:定义一个用于创建对象的接口,让子类决定实例化哪一个类,Factory Method使一个类的实例化延迟到了子类。
四、Builder,建造模式:将一个复杂对象的构建与他的表示相分离,使得同样的构建过程可以创建不同的表示。
五、Prototype,原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型来创建新的对象。
行为型有:六、Iterator,迭代器模式:提供一个方法顺序访问一个聚合对象的各个元素,而又不需要暴露该对象的内部表示。
七、Observer,观察者模式:定义对象间一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知自动更新。
八、Template Method,模板方法:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,TemplateMethod使得子类可以不改变一个算法的结构即可以重定义该算法得某些特定步骤。
九、Command,命令模式:将一个请求封装为一个对象,从而使你可以用不同的请求对客户进行参数化,对请求排队和记录请求日志,以及支持可撤销的操作。
十、State,状态模式:允许对象在其内部状态改变时改变他的行为。
对象看起来似乎改变了他的类。
十一、Strategy,策略模式:定义一系列的算法,把他们一个个封装起来,并使他们可以互相替换,本模式使得算法可以独立于使用它们的客户。
十二、China of Responsibility,职责链模式:使多个对象都有机会处理请求,从而避免请求的送发者和接收者之间的耦合关系十三、Mediator,中介者模式:用一个中介对象封装一些列的对象交互。
java设计模式面试题
java设计模式面试题Java 设计模式面试题设计模式是软件开发中常用的解决问题的方法论,它通过提供经过验证的解决方案来应对各种软件设计问题。
在面试中,设计模式也是经常被问到的内容之一。
本文将介绍一些常见的Java 设计模式面试题,并给出对应的解答。
一、单例模式(Singleton Pattern)单例模式是一种创建型设计模式,其目的是保证一个类只有一个实例,并提供一个全局访问点。
常见的实现方式有懒汉式和饿汉式。
1. 懒汉式实现单例模式的代码示例:```javapublic class Singleton {private static Singleton instance;private Singleton() {}public static Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}2. 饿汉式实现单例模式的代码示例:```javapublic class Singleton {private static Singleton instance = new Singleton();private Singleton() {}public static Singleton getInstance() {return instance;}}```二、工厂模式(Factory Pattern)工厂模式是一种创建型设计模式,其通过提供一个公共接口来创建对象,而不需要暴露对象的创建逻辑。
1. 简单工厂模式的代码示例:```javapublic interface Shape {void draw();public class Circle implements Shape {@Overridepublic void draw() {System.out.println("Draw a circle.");}}public class Rectangle implements Shape {@Overridepublic void draw() {System.out.println("Draw a rectangle.");}}public class ShapeFactory {public Shape createShape(String shapeType) {if (shapeType.equalsIgnoreCase("circle")) {return new Circle();} else if (shapeType.equalsIgnoreCase("rectangle")) { return new Rectangle();}return null;}}```2. 抽象工厂模式的代码示例:```javapublic interface Shape {void draw();}public interface Color {void fill();}public class Circle implements Shape { @Overridepublic void draw() {System.out.println("Draw a circle."); }}public class Rectangle implements Shape {@Overridepublic void draw() {System.out.println("Draw a rectangle."); }}public class Red implements Color {@Overridepublic void fill() {System.out.println("Fill with red color."); }}public class Blue implements Color {@Overridepublic void fill() {System.out.println("Fill with blue color."); }}public abstract class AbstractFactory {public abstract Shape createShape(String shapeType); public abstract Color createColor(String colorType);}public class ShapeFactory extends AbstractFactory {@Overridepublic Shape createShape(String shapeType) {if (shapeType.equalsIgnoreCase("circle")) {return new Circle();} else if (shapeType.equalsIgnoreCase("rectangle")) { return new Rectangle();}return null;}@Overridepublic Color createColor(String colorType) {return null;}}public class ColorFactory extends AbstractFactory {@Overridepublic Shape createShape(String shapeType) {return null;}@Overridepublic Color createColor(String colorType) {if (colorType.equalsIgnoreCase("red")) {return new Red();} else if (colorType.equalsIgnoreCase("blue")) {return new Blue();}return null;}}```三、观察者模式(Observer Pattern)观察者模式是一种行为型设计模式,其定义了对象之间的一对多依赖关系,使得当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
软件常见设计模式
软件常见设计模式1.创建型模式单例模式单例模式(Singleton Pattern)是⼀种常⽤的软件设计模式,该模式的主要⽬的是确保某⼀个类只有⼀个实例存在。
当你希望在整个系统中,某个类只能出现⼀个实例时,单例对象就能派上⽤场。
⽐如,某个服务器程序的配置信息存放在⼀个⽂件中,客户端通过⼀个 AppConfig 的类来读取配置⽂件的信息。
如果在程序运⾏期间,有很多地⽅都需要使⽤配置⽂件的内容,也就是说,很多地⽅都需要创建 AppConfig 对象的实例,这就导致系统中存在多个 AppConfig 的实例对象,⽽这样会严重浪费内存资源,尤其是在配置⽂件内容很多的情况下。
事实上,类似 AppConfig 这样的类,我们希望在程序运⾏期间只存在⼀个实例对象1 class Singleton(object):2 def __init__(self):3 pass45 def __new__(cls, *args, **kwargs):6 if not hasattr(Singleton, "_instance"): # 反射7 Singleton._instance = object.__new__(cls)8 return Singleton._instance910 obj1 = Singleton()11 obj2 = Singleton()12 print(obj1, obj2) #<__main__.Singleton object at 0x004415F0> <__main__.Singleton object at 0x004415F0>1 class Singleton(object):2 def __init__(self):3 pass45 def __new__(cls, *args, **kwargs):6 if not hasattr(Singleton, "_instance"): # 反射7 Singleton._instance = object.__new__(cls)8 return Singleton._instance910 obj1 = Singleton()11 obj2 = Singleton()12 print(obj1, obj2) #<__main__.Singleton object at 0x004415F0> <__main__.Singleton object at 0x004415F0>⼯⼚模式⼯⼚模式是⼀个在软件开发中⽤来创建对象的设计模式。
java常用的设计模式及应用场景
java常用的设计模式及应用场景一、单例模式(Singleton)单例模式是一种对象创建型模式,它指的是设计一个类,使其只能生成一个实例。
它只提供一个类实例,保证只有一个实例存在。
有时候,只需要一个类的实例来控制整个系统,例如实现一个全局的缓存,或是建立一个共享的日志记录器,单例模式可以很好的实现这个目的。
应用场景:1、对于需要频繁创建和销毁的对象,可以考虑使用单例模式,以避免过多地重复创建和销毁造成系统开销。
2、对于某些资源比较宝贵的对象,例如数据库连接,则可以用单例模式进行封装,保证全局应用程序只有一个,从而避免重复创建,浪费资源。
二、工厂模式(Factory)工厂模式是一种类创建型模式,它把类的实例化推迟到子类来完成。
它用于隔离客户类和实例化对象,通过声明抽象类类来定义构造过程,将不同的定义转移到不同的子类中去,从而使用户不需要关心实例化过程。
1、在有大量不同对象需要创建和管理的情况下,可以利用工厂模式封装类的实例化和存储,将池中不同对象来进行统一管理。
2、在使用设计模式的情况下,复杂的类结构已经不适合用一个实例来创建,可以采用工厂模式实现多个类的实例化,让用户不用关心对象实例的创建过程。
抽象工厂模式是一种工厂模式的拓展,它把简单工厂模式的单一职责拆分为多个类,从而实现一个系列相关的或相互依赖的工厂,以满足比较复杂的对象创建需求。
1、在需要创建复杂对象,而复杂对象又由多个部件组成的情况下,例如计算机,单一工厂模式已经不能满足需求,那么可以通过抽象工厂模式来实现。
2、在需要产生大量不同类型的对象,或者存在一系列相互依赖的产品族,这种情况下可以使用抽象工厂模式,将工厂定义为不同维度组成的一个系列。
四、建造者模式(Builder)建造者模式是一种设计模式,它也叫构造子模式,通过使用建造者模式,客户端可以不必担心具体的生产过程,只需要给出具体的请求,由建造者来负责构造出请求的产品对象。
1、在有复杂的产品对象的时候,例如需要对多个部件进行拼装,以构造出复杂的对象,可以采用建造者模式将复杂的拼装过程进行封装,避免复杂的拼装过程变得混乱。
23种设计模式 简单明了
23种设计模式简单明了1. 单例模式(Singleton Pattern):确保一个类只有一个实例,并提供全局访问点。
2. 工厂模式(Factory Pattern):定义创建对象的接口,但将实际创建对象的过程推迟到子类中。
3. 抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关对象的接口,而无需指定具体的类。
4. 建造者模式(Builder Pattern):将一个复杂对象的创建与表示分离,使同样的构建过程可以创建不同的表示。
5. 原型模式(Prototype Pattern):通过复制现有的对象来创建新对象。
6. 适配器模式(Adapter Pattern):将一个类的接口转换成客户希望的另一个接口。
7. 桥接模式(Bridge Pattern):将抽象与实现分离,使它们可以独立变化,从而减少两者之间的耦合。
8. 过滤器模式(Filter Pattern):通过某种条件来过滤一组对象。
9. 组合模式(Composite Pattern):将对象组合成树形结构,以表示 "部分-整体" 的层次结构。
10. 装饰器模式(Decorator Pattern):动态地给一个对象添加一些额外的职责。
11. 外观模式(Facade Pattern):隐藏系统的复杂性,并向客户端提供一个简化的接口。
12. 享元模式(Flyweight Pattern):共享对象,以便有效地支持大量细粒度的对象。
13. 代理模式(Proxy Pattern):为其他对象提供一种代理以控制对这个对象的访问。
14. 责任链模式(Chain of Responsibility Pattern):将请求的发送者和接收者解耦,并让多个对象都有机会处理这个请求。
15. 命令模式(Command Pattern):将请求封装成对象,从而允许使用不同的请求、队列或者日志请求。
16. 解释器模式(Interpreter Pattern):给定一个语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。
sqlsugar 单例
sqlsugar 单例在当今的软件开发领域,设计模式是工程师们解决各种问题的利器。
在数据库操作中,单例模式(Singleton Pattern)是一种常用的设计模式,它保证一个类仅有一个实例,并提供一个全局访问点。
本文将详细介绍sqlsugar单例模式,包括其意义、实现原理、应用场景、优缺点以及价值与启示。
一、概述sqlsugar单例模式的意义和作用sqlsugar单例模式是一种数据库操作框架,它致力于简化SQL语句的编写和执行过程,提高开发效率。
通过单例模式,我们可以确保在整个应用中只有一个数据库操作实例,避免了重复创建和销毁实例的性能开销。
同时,单例模式还提供了一个全局访问点,方便其他模块统一调用。
二、详细解析sqlsugar单例模式的实现原理sqlsugar单例模式的实现主要依赖于静态单例类和静态方法。
在静态单例类中,我们可以看到以下关键代码:1.私有化构造方法,防止外部实例化。
2.静态方法用于获取单例实例,确保全局唯一。
```javapublic class SqlSugar {// 私有化构造方法,防止外部实例化private SqlSugar() {}// 静态方法,用于获取单例实例public static SqlSugar getInstance() {if (instance == null) {synchronized (SqlSugar.class) {if (instance == null) {instance = new SqlSugar();}}}return instance;}}```三、阐述sqlsugar单例模式在实际项目中的应用场景在实际项目中,sqlsugar单例模式可以应用于以下场景:1.数据库连接池管理:通过单例模式实现数据库连接池,可以确保在整个应用中只有一个连接池实例,提高资源利用率。
2.数据库操作封装:将数据库操作封装为单例模式,可以简化代码,降低模块间的耦合度。
DCL_单例模式
DCL_单例模式简介单例模式(Singleton Pattern)是 Java 中最简单的设计模式之⼀。
这种类型的设计模式属于创建型模式,它提供了⼀种创建对象的最佳⽅式。
这种模式涉及到⼀个单⼀的类,该类负责创建⾃⼰的对象,同时确保只有单个对象被创建。
这个类提供了⼀种访问其唯⼀的对象的⽅式,可以直接访问,不需要实例化该类的对象。
为什么使⽤单例模式:多个线程操作不同实例对象。
多个线程要操作同⼀对象,要保证对象的唯⼀性优点:1、在内存⾥只有⼀个实例,减少了内存的开销2、避免对资源的多重占⽤单例模式的分类在对⽐每个模式通常往⼀下三个⽅⾯:线程的安全性、性能、懒加载(lazy )1.饿汉式:public class HungerySingleton {//加载的时候就产⽣的实例对象private static HungerySingleton instance=new HungerySingleton();private HungerySingleton(){}//返回实例对象public static HungerySingleton getInstance(){return instance;}public static void main(String[] args) {for (int i = 0; i < 20; i++) {new Thread(()->{System.out.println(HungerySingleton.getInstance());}).start();}}}线程安全性:在加载的时候已经被实例化,所以只有这⼀次,线程安全的懒加载:没有延迟加载,好长时间不使⽤,影响性能性能:性能⽐较好2.懒汉式public class HoonSingleton {private static HoonSingleton instance=null;private HoonSingleton(){}public static HoonSingleton getInstance(){if(null==instance)instance=new HoonSingleton();return instance;}public static void main(String[] args) {for (int i = 0; i < 20; i++) {new Thread(()->{System.out.println(HoonSingleton.getInstance());}).start();}}}线程安全:不能保证实例对象的唯⼀性,⾮线程安全懒加载:引发了⼀个不安全的问题,对于单例模式的应⽤有风险,⽽且风险⽐较⼤,,实现了懒加载性能:相对于饿汉式还是⽐较好的3.懒汉式+同步⽅法线程安全:是线程安全懒加载:是懒加载性能:+synchronized 退化到了串⾏执⾏4.Double-Check-Lockingpublic class DCL {private static DCL instance=null;private DCL(){}public static DCL getInstance(){if(null==instance)synchronized (DCL.class){if(null==instance)instance=new DCL();}return instance;}public static void main(String[] args) {for (int i = 0; i < 20; i++) {new Thread(()->{System.out.println(DCL.getInstance());}).start();}}}性能⽐较好懒加载:实现了懒加载线程的安全性:保证了线程的安全5.Volatile+Double-check只需要加⼀段代码:private volatile static DCL instance=null;可以避免空指针异常6.Holder声明类的时候,成员变量中不声明实例变量,⽽放到内部静态类中public class HolderDemo {private HolderDemo(){}private static class Holder{private static HolderDemo instance=new HolderDemo();}//懒加载//synchronized//<init>public static HolderDemo getInstance(){return Holder.instance;}//⼴泛的⼀种单例模式}7.枚举public class EnumSingletonDemo {private EnumSingletonDemo(){}//延迟加载private enum EnumHolder{INSTANCE;private static EnumSingletonDemo instance=null; private EnumSingletonDemo getInstance(){instance=new EnumSingletonDemo();return instance;}}//懒加载public static EnumSingletonDemo getInstance(){return EnumHolder.INSTANCE.instance;}}。
23种设计模式 详解
23种设计模式详解设计模式是指面向对象编程中,经过多次验证、被广泛接受的代码实现方法。
这些设计模式可以帮助开发者更快地解决问题,提高代码的可读性、可维护性、可扩展性。
目前,常用的设计模式有23种。
下面,我们来详细介绍一下这23种设计模式。
1. 单例模式(Singleton)单例模式是一种只允许生成一个实例的模式。
在实例化对象时,单例模式的生成过程比较特殊,需要先判断该类是否已经实例化过,如果已经实例化,则直接返回已有的实例对象,否则再进行实例化。
2. 工厂模式(Factory)工厂模式是一种生产对象实例的设计模式。
它将对象实例的生成过程封装在一个工厂类中,客户端需要对象时,只需要调用工厂类中对应的方法即可。
3. 抽象工厂模式(Abstract Factory)抽象工厂模式是一种扩展了工厂模式的模式。
它可以生成一系列相关或相互依赖的对象实例。
具体实现时,通常需要定义一个抽象工厂类和一些具体工厂类,来生产各种相关的对象实例。
4. 建造者模式(Builder)建造者模式是一种用于构建复杂对象的模式。
它将一个复杂对象的构建过程分解成多个简单的步骤,然后通过一个指挥者来管理这些步骤的执行,最终构建出一个复杂的对象。
5. 原型模式(Prototype)原型模式是一种通过复制已有对象来创建新对象的模式。
一般来说,系统中的对象包含大量相同或相似的部分,通过复制对象可以帮助我们节省生成对象的时间和资源。
6. 适配器模式(Adapter)适配器模式是一种将不兼容接口转换为兼容接口的模式。
具体实现时,需要定义一个适配器类,该类实现了客户端所期望的接口,而且还包装了原有不兼容的接口,使其能够兼容客户端期望的接口。
7. 桥接模式(Bridge)桥接模式是一种将抽象部分与其实现部分分离开来的模式。
具体实现时,需要定义抽象部分和实现部分的接口,然后定义一个桥接类,将抽象部分和实现部分联系起来。
8. 组合模式(Composite)组合模式是一种将具有相同属性和方法的对象组合成树形结构的模式。
设计模式在项目中的应用
设计模式在项目中的应用在软件开发中,设计模式是一种被广泛使用的解决方案。
设计模式是针对特定问题的常见解决方法,这些问题通常是软件工程中的常见难题。
使用设计模式的好处在于它能够提高代码复用性、可扩展性和可维护性,并且能够帮助开发人员理解代码的逻辑和结构。
设计模式的使用需要谨慎处理。
尽管设计模式是一种好的解决方案,但是过度使用设计模式也会带来问题。
在使用设计模式时需要评估其对代码的影响。
如果设计模式的优点不能够为项目带来优势,那么就需要谨慎考虑其是否应该使用。
下面我们就来看看在项目中,设计模式的应用。
一、单例模式(Singleton)在设计模式中,单例模式是一种创建型模式,用于保证在整个应用程序中只有一个实例存在。
单例模式通常用于控制资源的访问,例如数据库连接池或文件系统。
在软件开发中,单例模式的应用非常广泛。
举个例子,假设我们需要在程序中保留当前登录用户的信息。
我们可以使用单例模式创建一个用户会话(Session),在整个程序的生命周期内只有一个用户会话对象,可以确保我们在任何地方都能够访问到当前用户的信息。
二、工厂模式(Factory)工厂模式是一种创建型模式,提供了一种创建对象的统一接口,通过对这个接口的实现来指定创建哪个类的实例。
工厂模式可以将具体类的实例化过程与客户端分离,从而达到松耦合的目的。
在实际工程中,工厂模式的应用非常广泛。
在多态编程中,我们经常需要根据不同的条件生成不同的对象实例。
例如,我们可能需要根据数据源的不同来创建不同的数据库连接对象。
这时可以使用工厂模式,根据数据源的不同来创建不同的连接对象。
三、装饰器模式(Decorator)装饰器模式是一种结构型模式,它允许对象动态地添加责任,而又不影响其他对象。
装饰器模式通常用于为对象添加一些功能,这些功能通常是可选的,并且可以通过动态地为对象增加装饰器来添加。
在实际开发中,装饰器模式非常常见。
举个例子,假设我们需要为一系列文本文件添加行号,我们可以使用装饰器模式创建一个行号装饰器,通过给文件对象动态地增加该装饰器来完成添加行号的操作。
安卓中设计模式及应用场景
安卓中设计模式及应用场景设计模式是指在软件开发中可复用的解决问题的经验总结和最佳实践。
在安卓开发中,设计模式能帮助我们构建可维护、可扩展和可重用的应用程序。
下面将介绍几种常见的设计模式及其在安卓开发中的应用场景。
1. 单例模式(Singleton Pattern):单例模式用于确保一个类只有一个实例,并提供一个全局访问点。
在安卓开发中,有些情况下我们只需要一个全局对象,例如数据库管理器、网络请求管理器等。
通过单例模式可以确保只有一个实例存在,方便在各处进行访问。
2. 观察者模式(Observer Pattern):观察者模式定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,其依赖的对象们会收到通知并作出相应的更新。
在安卓中,我们可以利用观察者模式实现事件总线来进行组件之间的通信,例如使用EventBus库。
当某一组件的状态变化时,可以通过事件总线通知其他组件进行相应的操作。
3. 工厂模式(Factory Pattern):工厂模式定义了一个创建对象的接口,由子类决定实例化哪个类。
在安卓开发中,工厂模式经常用于创建各种不同类型的对象,能很好地实现解耦和复用。
例如在RecyclerView 的Adapter 中,在不同的情况下需要创建不同的ViewHolder,可以使用工厂模式根据需求创建不同的ViewHolder。
4. 适配器模式(Adapter Pattern):适配器模式将一个类的接口转换成客户端所期望的另一个接口,从而使得原本不兼容的类能够一起工作。
在安卓中,ListView 和RecyclerView 常常需要使用适配器来将数据源与界面进行绑定,使得数据能够正确地显示在界面上。
5. 建造者模式(Builder Pattern):建造者模式将一个复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。
在安卓开发中,用于构建复杂的对象可以使用建造者模式。
例如,在创建一个对话框时,可以通过使用建造者模式来设置对话框的标题、按钮、样式等属性,使得创建过程更加灵活和可扩展。
Java设计模式知识要点
AbstractClass 叫做抽象模板,它的方法分为两类: ● 基本方法 基本方法也叫做基本操作,是由子类实现的方法,并且在模板方法被调用。 ● 模板方法 可以有一个或几个,一般是一个具体方法,也就是一个框架,实现对基本方法的调 度,完成固定的逻辑。 注意: 为了防止恶意的操作,一般模板方法都加上 final 关键字,不允许被覆 写。 具体模板:ConcreteClass1 和 ConcreteClass2 属于具体模板,实现父类所定义的 一个或多个抽象方法,也就是父类定义的基本方法在子类中得以实现 使用场景: ● 多个子类有公有的方法,并且逻辑基本相同时。 ● 重要、复杂的算法,可以把核心算法设计为模板方法,周边的相关细节功能则由 各个子类实现。 ● 重构时,模板方法模式是一个经常使用的模式,把相同的代码抽取到父类中,然 后通过钩子函数(见“模板方法模式的扩展”)约束其行为。
2.工厂模式
定义:Define an interface for creating an object,but let subclasses decide which class to instantiate.Factory Method lets a class defer instantiation to subclasses. (定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类 的实例化延迟到其子类。)
项目中用到了哪些设计模式
项目中用到了哪些设计模式在项目中使用设计模式是提高代码质量、可维护性和可测试性的一种方法。
以下是项目中可能使用到的一些常见设计模式及其应用场景。
1. 单例模式(Singleton Pattern)单例模式用于限制一个类只有一个实例,并提供一个全局访问点。
在项目中,例如使用单例模式管理数据库连接、线程池、日志记录器等资源。
2. 工厂模式(Factory Pattern)工厂模式用于创建对象,而不必指定具体的类型。
在项目中,例如使用工厂模式创建具体的产品对象,根据不同的条件返回不同的实例。
3. 观察者模式(Observer Pattern)观察者模式用于定义一种一对多的依赖关系,让多个观察者对象同时监听其中一个主题对象。
在项目中,例如使用观察者模式实现事件监听器,当一些事件发生时,触发监听器的相应方法。
4. 装饰器模式(Decorator Pattern)装饰器模式用于动态地给一个对象添加一些额外的功能,而无需修改其原始类。
在项目中,例如使用装饰器模式对已有的类进行功能扩展,而不影响原有的代码。
5. 策略模式(Strategy Pattern)策略模式用于定义算法族,将它们分别封装起来,使它们可以相互替换。
在项目中,例如使用策略模式封装不同的排序算法,根据不同的需求选择不同的排序策略。
6. 适配器模式(Adapter Pattern)适配器模式用于将一个类的接口转换成客户端所期待的另一种接口。
在项目中,例如使用适配器模式将第三方库的接口适配成自定义的接口,方便项目的集成和使用。
7. 迭代器模式(Iterator Pattern)迭代器模式用于顺序访问集合对象的元素,而不暴露其底层的表示。
在项目中,例如使用迭代器模式遍历数据集合,提供一种统一的方式来访问集合中的元素。
组合模式用于将对象组合成树形结构以表示“部分-整体”的层次结构。
在项目中,例如使用组合模式构建菜单、目录结构等复杂的层次结构。
9. 模板方法模式(Template Method Pattern)模板方法模式用于定义一个算法的骨架,将一些步骤的具体实现延迟到子类中。
Singleton模式在网络编程中的应用场景及优点
Singleton模式在网络编程中的应用场景及优点随着互联网的蓬勃发展,网络编程变得越来越重要。
单例模式(Singleton Pattern)是一种经过实践考验的设计模式,是一种将类的实例化限制为一个对象的方法。
这篇文章将为您介绍在网络编程中,Singleton模式的应用场景及优点。
一、应用场景1. 数据库连接池在网络编程中,经常需要访问数据库。
由于数据库连接是一种资源,只有少数的连接可以被打开,因此需要建立一个连接池,以便在程序中随时使用。
数据库连接池应用了Singleton模式,因为只需要创建一个连接池实例即可,不需要创建很多个实例。
2. 日志系统在大型的系统中,需要采集很多的日志信息。
为了管理和控制这些日志信息,需要采用Singleton模式来解决可能抛出的并发问题。
使用Singleton模式只需要一个日志实例就足够了,方便了日志文件的管理。
3. 缓存系统在大型的系统中,缓存系统也是必不可少的,因为访问磁盘上的数据会很慢。
有了缓存系统,可以直接来自内存中的数据,快速响应用户的请求。
而Singleton模式可以保证缓存数据的一致性和唯一性。
二、优点1. 简化开发Singleton模式减少了对象的实例化次数,避免了频繁的创建和销毁对象的过程,减少了系统的开销。
同时,Singleton模式也方便了应用程序的管理。
2. 提高性能由于Singleton模式只有一个实例,因此能够节省大量的系统资源,提高了系统的性能。
同时,实现Singleton模式也能够避免多线程下可能出现的问题。
3. 实现单一职责原则Singleton模式能够保证一个类只有一个实例,避免了多实例造成的冲突,同时也符合单一职责原则,不会有相互影响的类对接。
4. 易于升级如果需要对系统进行升级或者改变某一个类的实现方式,Singleton模式只需要改变一个类即可,不需要对整个系统进行修改。
总之,Singleton模式在网络编程中具有广泛的应用场景并且具有许多重要的优点。
设计模式面试题
设计模式面试题设计模式是软件开发过程中常用的一种设计思想和方法,在面试中也是一个重要的考察点。
下面将介绍一些常见的设计模式面试题,以及它们的解题思路和应用场景。
1. 单例模式(Singleton Pattern)单例模式是最常见的一种设计模式,它保证一个类只有一个实例,并提供一个全局访问点。
在面试中,常常会被问到如何实现单例模式,可能会有以下几种问题:- 如何实现线程安全的单例模式?- 如何避免反射破解单例模式?2. 工厂模式(Factory Pattern)工厂模式是一种创建型模式,用于创建对象的过程与客户端的代码分离,这样可以减少对象创建的复杂度。
在面试中,可能会被问到如何实现工厂模式,以及工厂模式与抽象工厂模式的区别和应用场景。
3. 观察者模式(Observer Pattern)观察者模式是一种行为型模式,它定义了一种一对多的依赖关系,当一个对象的状态发生改变时,它的所有依赖者都会收到通知并自动更新。
在面试中,可能会被问到观察者模式的实现方式,以及观察者模式与发布-订阅模式的区别。
4. 适配器模式(Adapter Pattern)适配器模式是一种结构型模式,它通过将不兼容的接口转换成可兼容的接口,使得不同类之间可以协同工作。
在面试中,可能会被问到适配器模式的应用场景,以及适配器模式和装饰器模式的区别。
5. 策略模式(Strategy Pattern)策略模式是一种行为型模式,它通过定义一系列算法类并将其封装起来,从而使得它们可以互相替换。
在面试中,可能会被问到策略模式的特点,以及与状态模式的区别和适用场景。
6. 装饰器模式(Decorator Pattern)装饰器模式是一种结构型模式,它通过动态地将责任附加到对象上,扩展对象的功能。
在面试中,可能会被问到装饰器模式的实现方式,以及装饰器模式和代理模式的区别。
7. 原型模式(Prototype Pattern)原型模式是一种创建型模式,它通过复制已有对象来生成新的对象,从而避免了对象创建的复杂性。
单一直线型模式案例
单一直线型模式案例单一直线型模式是一种软件设计模式,它被用来实现对象的单例(Singleton)模式。
下面是一个单一直线型模式的案例:假设我们有一个需要使用数据库连接的应用程序,如果每次我们需要连接数据库时都重新创建一个数据库连接对象,那么会浪费很多资源。
因此我们选择使用单例模式,确保只有一个数据库连接对象实例被创建并在整个应用程序中共享。
在单一直线型模式中,我们使用一个私有的静态变量来存储单例对象,并使用一个私有的构造函数和一个公有的静态方法来获取该单例。
下面是一个简单的Java实现示例代码:```javapublic class DatabaseConnection {private static DatabaseConnection instance;private DatabaseConnection() {// 私有构造方法,防止直接创建对象}public static synchronized DatabaseConnection getInstance() {if (instance == null) {instance = new DatabaseConnection();}return instance;}// 其它数据库相关代码}// 在整个应用程序范围内共享单例对象DatabaseConnection dbConnection = DatabaseConnection.getInstance();```在上面的示例代码中,使用了一个私有的构造函数来防止直接创建对象,只能通过公有的静态方法getInstance()来获取单例对象。
在getInstance()方法中,如果当前对象为null,说明还没有创建单例对象,需要先创建一个。
注意这个方法是同步的,因为单例对象只能有一个,需要确保线程安全。
整个应用程序中只有一个数据库连接对象实例,可以在任何地方使用。
这种设计模式可以减少对象的创建和销毁次数,提高应用程序的性能和效率。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
单实例Singleton设计模式可能是被讨论和使用的最广泛的一个设计模式了,这可能也是面试中问得最多的一个设计模式了。
这个设计模式主要目的是想在整个系统中只能出现一个类的实例。
这样做当然是有必然的,比如你的软件的全局配置信息,或者是一个Factory,或是一个主控类,等等。
你希望这个类在整个系统中只能出现一个实例。
当然,作为一个技术负责人的你,你当然有权利通过使用非技术的手段来达到你的目的。
比如:你在团队内部明文规定,“XX类只能有一个全局实例,如果某人使用两次以上,那么该人将被处于2000元的罚款!”(呵呵),你当然有权这么做。
但是如果你的设计的是东西是一个类库,或是一个需要提供给用户使用的API,恐怕你的这项规定将会失效。
因为,你无权要求别人会那么做。
所以,这就是为什么,我们希望通过使用技术的手段来达成这样一个目的的原因。
本文会带着你深入整个Singleton的世界,当然,我会放弃使用C++语言而改用Java语言,因为使用Java这个语言可能更容易让我说明一些事情。
Singleton的教学版本
这里,我将直接给出一个Singleton的简单实现,因为我相信你已经有这方面的一些基础了。
我们姑且把这具版本叫做1.0版
在上面的实例中,我想说明下面几个Singleton的特点:(下面这些东西可能是尽人皆知的,没有什么新鲜的)
私有(private)的构造函数,表明这个类是不可能形成实例了。
这主要是怕这个类会有多个实例。
即然这个类是不可能形成实例,那么,我们需要一个静态的方式让其形成实例:getInstance()。
注意这个方法是在new自己,因为其可以访问私有的构造函数,所以他是可以保证实例被创建出来的。
在getInstance()中,先做判断是否已形成实例,如果已形成则直接返回,否则创建实例。
所形成的实例保存在自己类中的私有成员中。
我们取实例时,只需要使用Singleton.getInstance()就行了。
当然,如果你觉得知道了上面这些事情后就学成了,那我给你当头棒喝一下了,事情远远没有那么简单。
Singleton的实际版本
上面的这个程序存在比较严重的问题,因为是全局性的实例,所以,在多线程情况下,所有的全局共享的东西都会变得非常的危险,这个也一样,在多线程情况下,如果多个线程同时调用getInstance()的话,那么,可能会有多个进程同时通过(singleton== null)的条件检查,于是,多个实例就创建出来,并且很可能造成内存泄露问题。
嗯,熟悉多线程的你一定会说——“我们需要线程互斥或同步”,没错,我们需要这个事情,于是我们的Singleton升级成1.1版,如下所示:
嗯,使用了Java的synchronized方法,看起来不错哦。
应该没有问题了吧?!错!这还是有问题!为什么呢?前面已经说过,如果有多个线程同时通过(singleton== null)的条件检查(因为他们并行运行),虽然我们的synchronized方法会帮助我们同步所有的线程,让我们并行线程变成串行的一个一个去new,那不还是一样的吗?同样会出现很多实例。
嗯,确实如此!看来,还得把那个判断(singleton== null)条件也同步起来。
于是,我们的Singleton
不错不错,看似很不错了。
在多线程下应该没有什么问题了,不是吗?的确是这样的,1.2版的Singleton在多线程下的确没有问题了,因为我们同步了所有的线程。
只不过嘛……,什么?!还不行?!是的,还是有点小问题,我们本来只是想让new这个操作并行就可以了,现在,只要是进入getInstance()的线程都得同步啊,注意,创建对象的动作只有一次,后面的动作全是读取那个成员变量,这些读取的动作不需要线程同步啊。
这样的作法感觉非常极端啊,为了一个初始化的创建动作,居然让我们达上了所有的读操作,严重影响后续的性能啊!
还得改!嗯,看来,在线程同步前还得加一个(singleton== null)的条件判断,如果对象已经创建了,那么就不需要线程的同步了。
OK,下面是1.3版的Singleton.
感觉代码开始变得有点罗嗦和复杂了,不过,这可能是最不错的一个版本了,这个版本又叫“双重检查”Double-Check.下面是说明:
第一个条件是说,如果实例创建了,那就不需要同步了,直接返回就好了。
不然,我们就开始同步线程。
第二个条件是说,如果被同步的线程中,有一个线程创建了对象,那么别的线程就不用再创建了。
相当不错啊,干得非常漂亮!请大家为我们的1.3版起立鼓掌!
Singleton的其它问题
怎么?还有问题?!当然还有,请记住下面这条规则——“无论你的代码写得有多好,其只能在特定的范围内工作,超出这个范围就要出Bug了”,这是“陈式第一定理”,呵呵。
你能想一想还有什么情况会让这个我们上面的代码出问题吗?
在C++下,我不是很好举例,但是在Java的环境下,嘿嘿,还是让我们来看看下面的一些反例和一些别的事情的讨论(当然,有些反例可能属于钻牛角尖,可能有点学院派,不过也不排除其实际可能性,就算是提个醒吧):
其一、Class Loader.不知道你对Java的Class Loader熟悉吗?“类装载器”?!C++可没有这个东西啊。
这是Java动态性的核心。
顾名思义,类装载器是用来把类(class)装载进JVM的。
JVM规范定义了两种类型的类装载器:启动内装载器(bootstrap)和用户自定义装载器(user-defined class loader)。
在一个JVM中可能存在多个ClassLoader,每个ClassLoader拥有自己的NameSpace.一个ClassLoader只能拥有一个class对象类型的实例,但是不同的ClassLoader可能拥有相同的class对象实例,这时可能产生致命的问题。
如ClassLoaderA,装载了类A的类型实例A1,而ClassLoaderB,也装载了类A的对象实例A2.逻辑上讲A1=A2,但是由于A1和A2来自于不同的ClassLoader,它们实际上是完全不同的,如果A中定义了一个静态变量c,则c在不同的ClassLoader中的值是不同的。
于是,如果咱们的Singleton 1.3版本如果面对着多个Class Loader会怎么样?呵呵,多个实例同样会被多个Class Loader创建出来,当然,这个有点牵强,不过他确实存在。
难道我们还要整出个1.4版吗?可是,我们怎么可能在我的Singleton类中操作Class Loader啊?是的,你根本不可能。
在这种情况下,你能做的只有是——“保证多个Class Loader不会装载同一个Singleton”。
其二、序例化。
如果我们的这个Singleton类是一个关于我们程序配置信息的类。
我们需要它有序列化的功能,那么,当反序列化的时候,我们将无法控制别人不多次反序列化。
不过,我们可以利用一下Serializable接口的readResolve()方法,比如:
其三、多个Java虚拟机。
如果我们的程序运行在多个Java的虚拟机中。
什么?多个虚拟机?这是一种什么样的情况啊。
嗯,这种情况是有点极端,不过还是可能出现,比如EJB或RMI之流的东西。
要在这种环境下避免多实例,看来只能通过良好的设计或非技术来解决了。
其四,volatile变量。
关于volatile这个关键字所声明的变量可以被看作是一种“程度较轻的同步synchronized”;与 synchronized 块相比,volatile 变量所需的编码较少,并且运行时开销也较少,但是它所能实现的功能也仅是synchronized的一部分。
当然,如前面所述,我们需要的Singleton 只是在创建的时候线程同步,而后面的读取则不需要同步。
所以,volatile变
量并不能帮助我们即能解决问题,又有好的性能。
而且,这种变量只能在JDK 1.5+版后才能使用。
其五、关于继承。
是的,继承于Singleton后的子类也有可能造成多实例的问题。
不过,因为我们早把Singleton的构造函数声明成了私有的,所以也就杜绝了继承这种事情。
其六,关于代码重用。
也话我们的系统中有很多个类需要用到这个模式,如果我们在每一个类都中有这样的代码,那么就显得有点傻了。
那么,我们是否可以使用一种方法,把这具模式抽象出去?在C++下这是很容易的,因为有模板和友元,还支持栈上分配内存,所以比较容易一些(程序如下所示),Java下可能比较复杂一些,聪明的你知道怎么做吗?。