zoukankan      html  css  js  c++  java
  • Java设计模式之单例模式

      设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的;设计模式使代码编制真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样(百度百科)。

    设计模式分类:

    创建型模式:

      单例模式、工厂模式、抽象工厂模式、建造者模式、原型模式

    结构型模式:

      适配器模式、桥接模式、装饰模式、组合模式、外观模式、代理模式

    行为模式:

      责任链模式、命令模式、策略模式、观察模式、解释器模式、迭代模式、中介模式、备忘录模式、状态模式、模板模式、访问者模式

    设计原则

      开闭原则: 一个软件实体应该对扩展开放 对修改闭合。

      里氏代换原则:  任何能使用父类的地方一定能使用子类。

      依赖倒转原则: 要依赖于抽象 不要依赖于实现。或者是抽象不应该依赖与细节,细节应该依赖于抽象。

      合成聚合复用原则: 尽量使用合成聚合而不是继承去实现复用。

      迪米特法则: 一个软件实体应该尽可能少的与其它实体发生相互作用。

      接口隔离原则: 应当为客户提供尽可能小的单独的接口 而不应该提供大的综合性的接口。

      今天自己学习了一下单例模式。

    单例模式的核心作用

      保证一个类只有一个实例,并且提供一个访问该实例的全局访问点。意味着只有一个存在的对象。

    单例的优点:

      只生成一个实例,减少系统开销,提高系统性能。

      提供一个全局的访问点,资源共享。

    单例的优点:

      扩展性比较差。

      滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为的单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;如果实例化的对象长时间不被利用,系统会认为是垃圾而被回收,这将导致对象状态的丢失。

    常见运用场景:

      代码中经常使用的读取配置文件的类,一般我们只会有一个对象。没有必要每次读取一个对象都创建新对象。

      Windows的任务管理器,怎么按都会只有一个出来。

      日志对象,我们一般也会使用单例。

    常见的5种单例模式实现方式:

      主要:

        饿汉式(线程安全、调用效率高。不能延时加载 以空间换时间)。

        懒汉式(线程安全、调用效率不高,可以延时加载 以时间换空间)。

      其他:

        双重检测锁式(JVM内存的“无序写入”问题 不建议使用)

        静态内部类式(线程安全、调用效率高,延时加载)

        枚举单例(线程安全、调用效率高,不能延时加载)

      懒汉式单例:

    package com.roc.singlet;
    
    /**
    
     * 懒汉式单例
    
     * @author liaowp
    
     *
    
     */
    
    public class SingletPatter1 {
    
    //类初始化时,立即加载这个对象。加载类时,线程安全。
    
    private static SingletPatter1 instance = new SingletPatter1();
    
     
    
    private SingletPatter1(){
    
     
    
    }
    
     
    
    public static SingletPatter1 getInstance(){
    
    return instance;
    
    }
    
    }

    懒汉式:

    package com.roc.singlet;
    
    /**
    
     * 懒汉式(线程安全、调用效率不高,可以延时加载 以时间换空间,对象延迟加载)。
    
     * @author liaowp
    
     *
    
     */
    
    public class SingletPatter2 {
    
    //初始化时没有立即创建对象。
    
    private static SingletPatter2 instance;
    
     
    
    //私有话构造器
    
    private SingletPatter2(){
    
     
    
    }
    
     
    
    public static synchronized SingletPatter2 getInstance(){
    
    if(instance==null){
    
    instance = new SingletPatter2();
    
    }
    
    return instance;
    
    }
    
    }

    主要特点:懒加载(延时加载)使用的时候才加载。

    存在问题:每次都要同步,并发效率低。

    怎么理解2种类型的单例:

      饿汉:想一想你饿的时候马上就想去吃东西,立即就加载,这就是饿汉。

      懒汉:即时自己很饿了,但是很懒。我想要吃的时才去吃。使用的时候才加载。这是懒汉。

    双重检测锁实现:

     1 package com.roc.singlet;
     2 
     3 /**
     4 
     5  * 双重检测锁实现
     6 
     7  * @author liaowp
     8 
     9  *
    10 
    11  */
    12 
    13 public class SingletPatter3 {
    14 
    15 public static SingletPatter3 instance = null;
    16 
    17  
    18 
    19 //每个模式将同步内容下发到if内部,提高执行效率。只有第一次才同步,创建以后就没有必要了
    20 
    21 public static SingletPatter3 getInstance(){
    22 
    23 if(instance==null){
    24 
    25 SingletPatter3 singletPatter3;
    26 
    27 synchronized (SingletPatter3.class) {
    28 
    29 singletPatter3 = instance;
    30 
    31 if(singletPatter3==null){
    32 
    33 synchronized (SingletPatter3.class) {
    34 
    35 if(singletPatter3==null){
    36 
    37 singletPatter3 = new SingletPatter3();
    38 
    39 }
    40 
    41 }
    42 
    43 instance = singletPatter3;
    44 
    45 }
    46 
    47 }
    48 
    49 }
    50 
    51 return instance;
    52 
    53 }
    54 
    55  
    56 
    57 private SingletPatter3(){
    58 
    59  
    60 
    61 }
    62 
    63 }

    存在问题:由于编译器优化原因和JVM底层内部模型原因。偶尔会出现问题。

    静态内部类的实现方式:

    package com.roc.singlet;
    
    /**
    
     * 静态内部类实现方式
    
     * @author liaowp
    
     *
    
     */
    
    public class SingletPatter4 {
    
     
    
    private static class SingletPatterInstance{
    
    private static SingletPatter4 instance = new SingletPatter4();
    
    }
    
     
    
    public static SingletPatter4 getInstance(){//使用到才去调用内部类加载方式,即懒加载
    
    return SingletPatterInstance.instance;
    
    }
    
     
    
    public SingletPatter4(){
    
     
    
    }
    
    }
    
    优点:
    
    外部没有static修饰,不会立即加载。
    
    Instance的是final static的类型,保证了内存中只有一个实例。线程安全。
    
    兼备并发高效的调用和延迟加载的优势。
    
    枚举实现方式
    
    package com.roc.singlet;
    
    /**
    
     * 枚举方式实现单例
    
     * @author liaowp
    
     *
    
     */
    
    public enum SingletPatter5 {  
    
        INSTANCE;  
    
    }  

    如何选择:

    单例对象,占用资源少,不需要延时加载的时候可以选择枚举式与饿汉式。

    枚举式  》   饿汉式。

    单例对象 占用资源大 需要延时加载:静态内部类式 懒汉式

    静态内部类式 》 懒汉式

    作者:鹏鹏
             
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。如有问题请联系906522957@qq.com
  • 相关阅读:
    对协程的一些理解
    JUC中Lock和ReentrantLock介绍及源码解析
    JUC中AQS简介
    Executor框架简介
    CyclicBarrier简介
    CountDownLatch简介
    Semaphore简介
    ThreadPoolExecutor简介
    AtomicInteger简介
    synchronized和volatile简介
  • 原文地址:https://www.cnblogs.com/liaoweipeng/p/5339415.html
Copyright © 2011-2022 走看看