java 设计模式 学习笔记(五)单例模式

简介:

单例模式:用来创建独一无二的,只能有一个实例的对象的入场券。

   一些对象,我们只需要一个:(线程池,缓存,对话框等等),事实上,这类对象只能有一个实例。如果制造多了了,会导致许多问题,如行为异常、资源使用过量。

   全局变量的缺点,如果将对象赋值给一个全局变量,那么必须在程序一开始就创建好对象,万一这个对象非常消耗资源,而程序在这次的执行过程中又一直没用到它,就形成了浪费。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public  class  Singleton {
     private  static  Singleton uniInstance;
     public  int  ID;
                                                                                                                                                                                                                                                                                                                                    
     private  Singleton( int  id) {
         ID = id;
     }
                                                                                                                                                                                                                                                                                                                                    
     public  static  Singleton getInstance( int  id) {
         if  (uniInstance ==  null ) {
             uniInstance =  new  Singleton(id);
         }
                                                                                                                                                                                                                                                                                                                                    
         return  uniInstance;
     }
}
                                                                                                                                                                                                                                                                                                                                   
//----------------------Main------------------------
                                                                                                                                                                                                                                                                                                                                   
public  class  Main {
     public  static  void  main(String[] args) {
         Singleton mSingleton,nSingleton;
         mSingleton = Singleton.getInstance( 3 );
         nSingleton = Singleton.getInstance( 4 );
         System.out.println(mSingleton.ID);
         System.err.println(nSingleton.ID);
     }
}


   打印出来的结果,都是3,说明mSingleton与nSingleton指向同一对象,保证了实例的唯一性。

请注意,如果不需要这个实例,它就永远不会产生。

   上述为单例模式的经典实现,再看下单例模式的定义:

   确保一个类只有一个实例,并提供一个全局访问点。

   把类设计成自己管理的一个单独实例,同时也避免其他类再自行产生实例。并且提供了这个实例的全局访问点:当你需要实例时,向类查询,它会返回单个实例。

   需要注意的是,Singleton声明的实例对象必须是全局的。假设上述代码中的

1
Singleton mSingleton,nSingleton;

是分别放在不同线程中声明的,那么getInstance获得的实例就不符合单件模式规则了。


   巧克力工厂:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
/**
  * 这是一个巧克力锅炉控制器,锅炉做的事,就是把巧克力和牛奶融在一起, 然后送到下一个阶段,以制造成巧克力棒
  */
                                                                   
public  class  ChocolateBoiler {
     private  boolean  empty; // 代码开始时,锅炉是空的
     private  boolean  boiled;
     public  ChocolateBoiler() {
         empty =  true ;
         boiled =  false ;
     }
                                                                   
     /**
      * 在锅炉内填入原料时,锅炉必须是空的。 一旦填入原料,就把empty和boiled标志设置好
      */
     public  void  fill() {
         if  (isEmpty()) {
             empty =  false ;
             boiled =  true ;
             // 在锅炉内填满巧克力和牛奶的混合物
         }
     }
                                                                   
     private  boolean  isEmpty() {
         return  empty;
     }
                                                                 
     private  boolean  isBoiled() {
         return  boiled;
     }
                                                                   
     /**
      * 锅炉排出时,必须是满的(不可以是空的)而且是煮过的。排出完毕后,把empty标志设回true
      */
     public  void  drain() {
         if  (!isEmpty() && isBoiled()) {
             // 排除煮沸的巧克力和牛奶
             empty =  true ;
         }
     }
                                                                   
     /**
      * 煮混合物时,锅炉必须是满的,并且是没有煮过的,一旦煮沸后,就把boiled标志设为true
      */
     public  void  boil() {
         if  (!isEmpty() && !isBoiled()) {
             // 将炉内物煮沸
             boiled =  true ;
         }
     }
}


   注意到了,如果同时存在两个以上ChocolateBoiler实例存在,可能会存在的问题:排除500升的为主费的混合物,或者锅炉已经满了还继续放原料,或者锅炉内还没放原料就开始空烧。修改下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public  class  ChocolateBoiler {
     private  boolean  empty; // 代码开始时,锅炉是空的
     private  boolean  boiled;
     private  static  ChocolateBoiler uniChocolateBoiler;
                                        
     private  ChocolateBoiler() {
         // TODO Auto-generated constructor stub
         empty =  true ;
         boiled =  false ;
     }
                                        
     public  static  ChocolateBoiler getInstance() {
         if  (uniChocolateBoiler ==  null ) {
             uniChocolateBoiler =  new  ChocolateBoiler();
         }
         return  uniChocolateBoiler;
     }
     //后面代码省略
}


   又遇到了麻烦,fill方法允许在加热的过程中继续假如原料,这可是会溢出五百升的原料。是多线程导致的问题。    

   处理多线程,只要把getInstance()变成同步(synchronized)方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
class  Singleton {
     private  static  Singleton uniqueInstance;
                               
     private  Singleton() {
     }
                               
     public  static  synchronized  Singleton getInstance() {
         if  (uniqueInstance ==  null ) {
             uniqueInstance =  new  Singleton();
         }
         return  uniqueInstance;
     }
}


综述

   1.单件模式确保程序中一个类最多只有一个实例

   2.单件模式也提供访问这个实例的全局点

   3.在java中实现单件模式需要

   (1)私有构造器

   (2)一个静态方法

   (3)一个静态变量

   4.确定在性能和资源上的限制,然后小心地选择适当的方案来实现单件,以解决多线程的问题


由于最近一直在学习Golang,所以之后学习的设计模式如果没有涉及到Java特有的语言特性,学习笔记中的源码将由Golang来完成










本文转自 ponpon_ 51CTO博客,原文链接:http://blog.51cto.com/liuxp0827/1353917,如需转载请自行联系原作者
目录
相关文章
|
1月前
|
设计模式 存储 前端开发
前端必须掌握的设计模式——单例模式
单例模式是一种简单的创建型设计模式,确保一个类只有一个实例,并提供一个全局访问点。适用于窗口对象、登录弹窗等场景,优点包括易于维护、访问和低消耗,但也有安全隐患、可能形成巨石对象及扩展性差等缺点。文中展示了JavaScript和TypeScript的实现方法。
|
1月前
|
设计模式 安全 Java
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
28 2
|
2月前
|
设计模式 消息中间件 搜索推荐
Java 设计模式——观察者模式:从优衣库不使用新疆棉事件看系统的动态响应
【11月更文挑战第17天】观察者模式是一种行为设计模式,定义了一对多的依赖关系,使多个观察者对象能直接监听并响应某一主题对象的状态变化。本文介绍了观察者模式的基本概念、商业系统中的应用实例,如优衣库事件中各相关方的动态响应,以及模式的优势和实际系统设计中的应用建议,包括事件驱动架构和消息队列的使用。
|
2月前
|
设计模式 Java 数据库连接
Java编程中的设计模式:单例模式的深度剖析
【10月更文挑战第41天】本文深入探讨了Java中广泛使用的单例设计模式,旨在通过简明扼要的语言和实际示例,帮助读者理解其核心原理和应用。文章将介绍单例模式的重要性、实现方式以及在实际应用中如何优雅地处理多线程问题。
46 4
|
2月前
|
设计模式 安全 Java
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
|
2月前
|
设计模式 安全 Java
Java编程中的单例模式:理解与实践
【10月更文挑战第31天】在Java的世界里,单例模式是一种优雅的解决方案,它确保一个类只有一个实例,并提供一个全局访问点。本文将深入探讨单例模式的实现方式、使用场景及其优缺点,同时提供代码示例以加深理解。无论你是Java新手还是有经验的开发者,掌握单例模式都将是你技能库中的宝贵财富。
77 2
|
2月前
|
设计模式 安全 Java
Java编程中的单例模式深入解析
【10月更文挑战第31天】在编程世界中,设计模式就像是建筑中的蓝图,它们定义了解决常见问题的最佳实践。本文将通过浅显易懂的语言带你深入了解Java中广泛应用的单例模式,并展示如何实现它。
|
2月前
|
设计模式 安全 Java
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
|
2月前
|
设计模式 安全 Java
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
31 0
|
2月前
|
Java 数据库连接 API
Spring 框架的介绍(Java EE 学习笔记02)
Spring是一个由Rod Johnson开发的轻量级Java SE/EE一站式开源框架,旨在解决Java EE应用中的多种问题。它采用非侵入式设计,通过IoC和AOP技术简化了Java应用的开发流程,降低了组件间的耦合度,支持事务管理和多种框架的无缝集成,极大提升了开发效率和代码质量。Spring 5引入了响应式编程等新特性,进一步增强了框架的功能性和灵活性。
61 0