<<设计模式>>读书笔记------单例模式

来源:互联网 发布:好的淘宝文案 编辑:程序博客网 时间:2024/05/21 10:54

一.单例模式动机与定义

在使用windows时候,在“任务栏”右击弹出窗口中选择“任务管理器”,可以打开windows的任务管理器窗口,但是无论如何,我们都没有办法同时打开第二个人任务管理器,也就是说,它在整个系统中只有唯一的一个实例。

1.1模式动机

如何保证一个类只有一个实例并且这个实例易于被访问呢?
定义一个全局变量可以保证对象随时可以被访问,但是不能防止我们实例化多个对象。
一个更高的解决办法是,让类自身负责保存它的唯一实例,这个类可以保证没有其他实例被创建,并且它可以提供一个访问该实例的方法。这就是单例模式的模式动机。

二.单例模式结构与分析

单例模式是所有设计模式中结构最为简单的模式,它只包含一个类,即单例类。

2.1模式结构

这里写图片描述
单例模式只包含一个Singleton(单例角色):在单例类的内部实现只生成一个实例,同时它提供一个getInstance()工厂方法,让客户可以使用它的唯一实例;为防止在外部对其实例化,将其构造函数设计为私有;在单例类内部定义了一个Singleton类型的静态对象,作为外部共享的唯一实例。

2.2模式分析

1.单例模式的目的是保证一个类仅有一个实例,并且提供一个访问他的全局节点。

2.单例类拥有一个私有构造函数,确保用户无法通过new关键字直接实例化它。

3.单例模式包含一个静态私有成员变量静态共有工厂方法。该工厂方法负责检验实例的存在性并且实例化自己,然后存储在静态成员变量中,以确保只有一个实例被创建。

一般情况下:实现代码如下:

public class Singleton{    private static Singleton instance=null; //静态私有成员变量    //私有构造函数    private Singleton()    {       }    //静态共有工厂方法,返回唯一实例    public static Singleton getInstance()    {        if(instance==null)            instance=new Singleton();           return instance;    }}

在单例模式的实现过程中需要注意以下三点:

1. 单例类的构造函数为私有
2. 提供一个自身的静态私有成员变量
3. 提供一个共有的静态工厂方法

三.单例模式实例与解析

3.1单例模式实例之身份证号码

1.实例说明
在现实生活中,居民身份证号码具有唯一性,同一个人不允许有多个身份证号码,第一次申请身份证时将给居民分配一个身份证号码,如果只有因为遗失等原因补办时,还是使用原来的身份证号码,不会产生新的号码。现在使用单例模式模拟该场景。

2.实例类图
这里写图片描述

3.实例代码及解释

public class IdentityCardNo{    private static IdentityCardNo instance=null;    private String no;    private IdentityCardNo()    {       }    public static IdentityCardNo getInstance()    {        if(instance==null)        {            System.out.println("第一次办理身份证,分配新号码!");            instance=new IdentityCardNo();            instance.setIdentityCardNo("No400011112222");               }        else        {            System.out.println("重复办理身份证,获取旧号码!");          }        return instance;    }    private void setIdentityCardNo(String no)    {        this.no=no;    }    public String getIdentityCardNo()    {        return this.no;    }}

4.辅助代码

public class Client{    public static void main(String a[])    {       IdentityCardNo no1,no2;       no1=IdentityCardNo.getInstance();       no2=IdentityCardNo.getInstance();       System.out.println("身份证号码是否一致:" + (no1==no2));       String str1,str2;       str1=no1.getIdentityCardNo();       str2=no1.getIdentityCardNo();       System.out.println("第一次号码:" + str1);       System.out.println("第二次号码:" + str2);       System.out.println("内容是否相等:" + str1.equalsIgnoreCase(str2));       System.out.println("是否是相同对象:" + (str1==str2));    }}

在客户端测试代码中定义了两个IdentityCardNo类型的对象,通过调用两次静态工厂方法getInstance()获取对象,然后判断他们的是狗相等;再通过业务方法getIdentityCardNo()获取封装在对象中的属性号码no值,判断两次no值是否相同。

5.结果及分析
这里写图片描述
两次创建的IdentityCardNo对象内存地址相同,是同一个对象;封装在其中的号码no属性不仅值相等,其内存地址也一致,是同一个成员属性。

四.单例模式效果与应用

4.1优缺点

1.主要优点

  1. 提供了对唯一实例的受控访问
  2. 节约系统资源
  3. 允许可变数目的实例

    2.主要缺点

  4. 没有抽象层,很难扩展

  5. 单例类职责过重,一定程度上违背了“单一职责原则”。因为单例类既充当了工厂角色,提供工厂方法,又充当了产品角色,包含一些业务方法,将产品的创建和产品本身的功能融合到一起。
  6. 滥用可能会带来一些负面问题。如:连接池溢出,对象丢失…

4.2模式使用环境

  1. 系统只需要一个实例对象
  2. 客户调用类的单个实例只允许使用一个公共访问点。
    单例模式有一个必要条件:在一个系统中要求一个类只有一个实例时,才应当使用单例模式。
    注意两个问题:
  3. 不要使用单例模式存取全局变量,最好将全局变量放到对应类的静态成员中。
  4. 不要将数据库连接做成单例,因为一个系统可能会与数据库有多个连接,并且在有连接池的情况下,应当尽可能即使释放连接。

五.单例模式扩展

1.饿汉式单例
饿汉式单例类实在Java语言中实现起来最方便的单例类,结构图如下:
这里写图片描述
代码如下:

class EagerSingleton{      private static final EagerSingleton instance=new EagerSingleton();      private EagerSingleton(){      }      public static EagerSingleton getInstance() {          return instance;    }  }

2.懒汉式单例
结构图:
这里写图片描述
代码:

class LazySingleton {    private static LazySingleton instance = null;    private LazySingleton() {    }    synchronized public static LazySingleton getInstance() {        if (instance == null) {            instance = new LazySingleton();        }        return instance;    }}

该懒汉式单例类实现静态工厂方法时,使用了同步化机制,以处理多线程环境。

3.饿汉式单例与懒汉式单例类比较

饿汉式单例类在自己被加载时就将自己实例化。单从资源利用效率角度来讲,这个比懒汉式单例类稍差些从速度和反应时间角度来讲,则比懒汉式单例类稍好些

懒汉式单例类在实例化时,必须处理好在多个线程同时首次引用此类时的访问限制问题,特别是当单例类作为资源控制器,在实例化时必然涉及资源初始化,而资源初始化很有可能耗费大量时间,这意味着出现多线程同时首次引用此类的机率变得较大,需要通过同步化机制进行控制。

六.小结

1.单例模式的目的是保证一个类仅有一个实例,并提供一个访问它的全局访问点。单例类拥有一个私有构造函数,确保用户无法通过new关键字直接实例化它。除此之外,该模式中包含一个静态私有成员变量与静态公有的工厂方法。该工厂方法负责检验实例的存在性并实例化自己,然后存储在静态成员变量中,以确保只有一个实例被创建。

2.单例模式的主要优点在于提供了对唯一实例的受控访问并可以节约系统资源;其主要缺点在于因为缺少抽象层而难以扩展,且单例类职责过重。

3.单例模式适用情况包括:系统只需要一个实例对象;客户调用类的单个实例只允许使用一个公共访问点。

0 0
原创粉丝点击