English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Beispiel zur Singleton-Muster in der Android-Programmierung und Design-Patterns

This article describes the Singleton pattern in Android programming design. Share it with everyone for reference, as follows:

1. Introduction

The Singleton pattern is one of the most widely used patterns, and it may also be the only design pattern that many junior engineers know. When applying this pattern, the class of the Singleton object must ensure that only one instance exists. Many times, the entire system only needs to have one global object, which is conducive to coordinating the overall behavior of the system.

2. Definition

Ensure that a certain class has only one instance and that it instantiates itself and provides this instance to the entire system.

3. Usage Scenarios

Ensure that a class has only one object, to avoid excessive resource consumption from multiple objects, or that only one object of a certain type should exist. For example, if creating an object requires a lot of resources, such as accessing IO and database resources, then it is necessary to consider using the Singleton pattern.

4. Implementation Methods

1、Eager Initialization Pattern

Beispielcode:

/**
 * Eager Initialization Pattern
 */
public class Singleton {
  private static Singleton instance;
  private Singleton(){}
  public static Singleton getInstance(){
    if(instance == null){
      instance = new Singleton();
    
    return instance;
  

优点:Lazy loading (load when needed)

缺点:Not thread-safe, it is easy to encounter unsynchronized situations in a multi-threaded environment, such as frequent read and write operations on database objects.

2、Lazy Initialization Pattern

Beispielcode:

/**
 * Lazy Initialization Pattern
 */
public class Singleton {
  private static Singleton instance;
  private Singleton(){}
  public static synchronized Singleton getInstance(){
    if(instance == null){
      instance = new Singleton();
    
    return instance;
  

Im Vergleich zum饿汉模式 wurde der Schlüsselwort 'synchronized' in die getInstance-Methode hinzugefügt, das bedeutet, getInstance ist eine synchrone Methode, das ist eine Methode, um die Einzigartigkeit des Singleton-Objekts in multi-threaded-Situationen zu gewährleisten. Aber wenn man darüber nachdenkt, könnte man möglicherweise ein Problem bemerken, selbst wenn instance bereits initialisiert wurde (instance wird beim ersten Aufruf initialisiert), wird bei jedem Aufruf der getInstance-Methode synchronisiert, was unnötige Ressourcen verbraucht, das ist auch das größte Problem des Lazy-Ham-Pattern.

优点:Es löst das Problem der nicht sicheren Threads.

缺点:Bei der ersten Ladezeit ist es notwendig, die Instanziierung rechtzeitig durchzuführen, die Reaktion ist etwas langsamer, der größte Problem ist, dass bei jedem Aufruf von getInstance die Synchronisierung durchgeführt wird, was unnötige Synchronisationskosten verursacht.

Supplementary:Diese Singleton-Methode wird im Android-Quellcode verwendet, z.B. InputMethodManager, AccessibilityManager und andere verwenden dieses Singleton-Pattern

3、Double Check Lock (DCL) Double Check Locking

Beispielcode:

/**
 * Double-Check-Locking (DCL) Singleton-Pattern
 */
public class Singleton {
  private static Singleton instance;
  private Singleton(){}
  public static Singleton getInstance(){
    if(instance == null){
      synchronized (Singleton.class) {
        if(instance == null) {
          instance = new Singleton();
        
      
    
    return instance;
  

Der Highlight dieser Anwendung liegt natürlich in der getInstance-Methode, man kann sehen, dass getInstance die instance zwei Mal prüft: Die erste Prüfung dient hauptsächlich dazu, unnötige Synchronisierung zu vermeiden, die zweite Prüfung ist dazu da, um eine Instanz zu erstellen, wenn null ist.

Angenommen, Thread A führt die Anweisung instance = new Singleton() aus, hier scheint es sich um einen Befehl zu handeln, aber in der Tat ist es nicht eine atomare Operation, dieser Befehl wird letztlich in mehrere Assembler-Befehle kompiliert und macht etwa3Eine Sache:

(1)Speicherbereiche für Singleton-Instanzen zuweisen;

(2)aufruft den Konstruktor von Singleton() und initialisiert die Mitgliedsfelder;

(3)den instance-Objekt auf den zugewiesenen Speicherbereich verweist (in diesem Moment ist instance nicht mehr null).

da der Java-Compiler die Prozessorenumsortierung erlaubt sowie JDK1.5wurde in der Vorschrift der Cache-, Register- und Main-Memory-Write-Back-Reihenfolge des JMM (Java Memory Model, also Java-Memory-Modell) vor der1-2-3könnte es auch sein1-3-2Falls letzteres der Fall ist und3Execution completed,2Before the execution, it is switched to thread B, at this time, because instance has been executed the third point in thread A, instance is non-null, all, thread B directly takes instance, and when it is used again, it will fail, this is the DCL failure problem, and such difficult-to-track and difficult-to-reproduce errors may hide for a long time.

in JDK1.5After that, SUN officially noticed this problem, adjusted the JVM, and specified the volatile keyword. Therefore, if the JDK is1.5or later versions, you just need to change the definition of instance to private volatile static Singleton instance to ensure that the instance object is read from the main memory each time, and you can use the DCL writing method to complete the singleton pattern. Of course, volatile will affect performance to some extent, but considering the correctness of the program, sacrificing this performance is still worth it.

优点:High resource utilization, the singleton object is instantiated only when getInstance is executed for the first time, which is efficient. Under scenarios with few concurrency and low security, the singleton pattern may run perfectly.

缺点:First-time loading may be slightly slow, and it may also fail occasionally due to the Java memory model. There are also certain defects in high-concurrency environments, although the probability is very low.

Supplementary:In the open-source Android image project Android-Universal-Image-Loader (https://github.com/nostra13/Android-Universal-Image-Loader)uses this method.
The DCL pattern is the most commonly used singleton implementation method. It can instantiate the singleton object only when needed and can ensure the uniqueness of the singleton object in most scenarios, unless your code is more complex in concurrent scenarios or below JDK6version, otherwise, this method generally meets the needs.

4、Static inner class singleton pattern

Although DCL (Double-Checked Locking) solves problems such as resource consumption, unnecessary synchronization, and thread safety to some extent, it still fails in some cases. This problem is known as the failure of double-checked locking (DCL failure), and it is discussed at the end of the book 'Java Concurrency in Practice'. It points out that this 'optimization' is ugly and not recommended for use. Instead, it suggests using the following code as an alternative:

Beispielcode:

/**
 * Static inner class singleton pattern
 */
public class Singleton {
  private Singleton(){}
  public static Singleton getInstance(){
    return SingletonHolder.instance;
  
  /**
   * Static inner class
   * Lazy loading, reducing memory consumption
   */
  private static class SingletonHolder{}}
    private static final Singleton instance = new Singleton();
  

Beim ersten Laden der Singleton-Klasse wird instance nicht initialisiert, sondern instance wird erst initialisiert, wenn die getInstance-Methode von Singleton zum ersten Mal aufgerufen wird. Daher führt der erste Aufruf von getInstance dazu, dass die Virtuelle Maschine die SingletonHolder-Klasse lädt, was nicht nur die Thread-Sicherheit sicherstellt, sondern auch die Einzigartigkeit des Singleton-Objekts, sowie die Verzögerung der Instanzierung des Singleton, daher ist dies die empfohlene Implementierung des Singleton-Patterns.

优点:Verzögerte Ladezeit, thread-sicher (java-ladungszeitliche Mutex im Class-Laden), reduziert auch den Speicherverbrauch

5,Enum-Singleton

Einige Implementierungen des Singleton-Patterns wurden gezeigt, aber diese Implementierungen sind entweder etwas umständlich oder zeigen in bestimmten Situationen Probleme.

Beispielcode:

/**
 * Enum-Singleton-Pattern
 */
public enum Singleton {
  /**
   * 1.Von Java1.5Beginnt zu unterstützen;
   * 2.Ohnegebühren bieten Serialisierungsmechanismus;
   * 3.Absolute Verhinderung mehrfacher Instanzierung, selbst bei komplexen Serialisierungs- oder Reflections-Angriffen;
   */
  instance;
  private String others;
  Singleton() {
  
  public String getOthers() {
    return others;
  
  public void setOthers(String others) {
    this.others = others;
  

Die einfache Schreibweise ist der größte Vorteil des Enum-Singletons, Enum ist in Java mit gewöhnlichen Klassen identisch und kann sowohl Felder als auch eigene Methoden haben. Wichtigster ist, dass die Erstellung der Standard-Enum-Instanz thread-sicher ist und in jeder Situation ein Singleton ist.

Warum sage ich das? In den verschiedenen Implementierungen des Singleton-Patterns gibt es eine Situation, in der sie Objekte neu erstellen, nämlich bei der Deserialisierung.

Durch Serialisierung kann eine Instanz eines Singleton-Objekts auf die Festplatte geschrieben und anschließend zurückgelesen werden, um eine Instanz effektiv zu erhalten. Selbst wenn der Konstruktor privat ist, kann bei der Deserialisierung durch einen speziellen Weg ein neuer Instanz der Klasse erstellt werden, was dem Aufruf des Konstrukteurs der Klasse entspricht. Die Deserialisierung bietet einen speziellen Hook-Funktion, eine private, von der Instanz realisierte Methode readResolve(), die es den Entwicklern ermöglicht, die Deserialisierung des Objekts zu steuern. Zum Beispiel, um sicherzustellen, dass die Singleton-Objekte nicht neu erstellt werden, wenn sie deserialisiert werden, müssen Sie die folgende Methode hinzufügen:

private Object readResolve() throws ObjectStreamException {
  return instance;

也就是在readResolve方法中将instance对象返回,而不是默认的重新生成一个新的对象。而对于枚举,并不存在这个问题,因为即使反序列化它也不会重新生成新的实例。

优点:无偿提供序列化机制,绝对防止多次实例化,即使在面对复杂的序列化或反射攻击时。

缺点:从Java1.5开始支持。

上面主要介绍了单例模式5有各种创建方法,大家可以根据其优缺点在其个人实际项目中使用。

更多关于Android相关内容的读者可查看本站专题:《Android开发入门与进阶教程》、《Android调试技巧与常见问题解决方法汇总》、《Android基本组件用法总结》、《Android视图View技巧总结》、《Android布局layout技巧总结》及《Android控件用法总结》

希望本文所述对大家的Android程序设计有所帮助。

声明:本文内容来源于网络,版权归原创者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未进行人工编辑处理,也不承担相关法律责任。如果您发现有关版权的内容,欢迎发送邮件至:notice#oldtoolbag.com(在发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。

Möchten Sie auch sehen