`
java苹果+番茄
  • 浏览: 67993 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

单例(Singleton)模式【创建模式第四篇】

阅读更多
单例(Singleton)模式:单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单例类
1、单例模式的要点:
1) 某个类只能有一个实例
2) 它必须自行创建这个实例
3) 它必须自行向整个系统提供这个实例
2、单例模式的例子:
1) 打印机
2) 传真机使用的传真卡,只应该由一个软件管理
3) Windows回收站

3、单例模式有以下特点:
1) 单例类只能有一个实例
2) 单例类必须自己创建自己的唯一的实例
3) 单例类必须给所有其他对象提供这一实例
*饿汉式单例类:
			public class EagerSingleton{
				private static final EagerSingleton m_instance = new EagerSingleton();
				
				private EagerSingleton(){}
				
				public static EagerSingleton getInstance(){
					return m_instance;
				}
			}
		java语言中单例类的一个最重要的特点是类的构造子是私有的,从而避免外界利用构造子直接创建出任意多的实例。
		因为构造子是私有的,因此此类不能被继承
		
		*懒汉式单例类:
			与饿汉式单例类相同的是,类的构造子是私有的,不同的是在第一次被引用时将自己实例化,如果加载器是静态的,那么在懒汉
			式单例类被加载时不会将自己实例化。
			public class LazySingleton{
				private static LazySingleton m_instance = null;
				
				private LazySingleton(){}
				
				synchronized public static LazySingleton getInstance(){
					if(m_instance == null){
						m_instance = new LazySingleton();
					}
					return m_instance;
				}
			}
		
		*登记式单例类
			public class RegSingleton{
				private static HashMap m_registry = new HashMap();
				
				static{
					RegSingleton x = new RegSingleton();
					m_registry.put(x.getClass().getName(),x);
				}
				
				protected RegSingleton(){}
				
				public static RegSingleton getInstance(String name){
					if(name == null){
						name = "RegSingleton";
					}
					if(m_registry.get(name) == null){
						try{
							m_registry.put(name,Class.forName(name).newInstance());
						}catch(Exception e){
							System.out.println("Error happened.");
						}
					}
					return (RegSingleton)(m_registry.get(name));
				}
				//一个示意性的商业方法
				public String about(){
					return "Hello, I am RegSingleton";
				}
			} 
			
			//登记式单例类的子类
			public class RegSingletonChild extends RegSingleton{
				public RegSingletonChild(){}
				
				//静态工厂方法	
				public static RegSingletonChild getInstance(){
					return (RegSingletonChild)RegSingleton.getInstance("RegSingleton")
				}
				
				public String about(){
					return "Hello, I am RegSingletonChild";
				}
			}
		


4、使用单例模式的条件:
		使用单例模式有一个必要条件:在一个系统要求一个类只有一个实例时才应当使用单例模式,反过来说,如果一个类可以有几个实例共
		存,那么就没有必要使用单例模式类。
		
		//属性管理器
		import java.util.Properties;
		import java.io.FileInputStream;
		import java.io.File;
		
		public class ConfigManager{
			//属性文件全名
			private static final String PFILE = System.getProperty("user.dir")
			+ File.Separator + "Singleton.properties";
			//对应于属性文件的文件对象变量
			private File m_file = null;
			//属性文件的最后修改日期
			private long m_lastModifiedTime = 0;
			//属性文件所对应的属性对象变量
			private Properties m_props = null;
			//本类可能存在的唯一的一个实例
			private static ConfigManager m_instance = new ConfigManager();
			//私有的构造子,用以保证外界无法直接实例化
			private ConfigManager(){
				m_file = new File(PFILE);
				m_lastModifiedTime = m_file.lastModified();
				if(m_lastModifiedTime == 0){
					System.out.println(PFILE + "file does not exits!");
				}
				m_props = new Properties();
				try{
					m_props.load(new FileInputStream(PFILE));
				}catch(Exception e){
					e.printStackTrace();
				}	
			}
			//静态工厂方法
			public synchronized static ConfigManager getInstance(){
				return m_instance;
			}
			//读取一个属性项
			//@name_名称,defaultVal_属性项的默认值,
			public final Object getConfigItem(String name, Object defaultVal){
				long newTime = m_file.lastModified();
				if(newTime == 0){
					if(m_lastModifiedTime == 0){
						System.err.println(PFILE + "file does not exits!");
					}else{
						System.err.println(PFILE + "file was deleted!");
					}
					return defaultVal;
				}else if(newTime > m_lastModifiedTime){
					m_props.clear();
					try{
						m_props.load(new FileInputStream(PFILE));
					}catch(Exception e){
						e.printStackTrace();
					}
				}
				m_lastModifiedTime = newTime;
				Object val = m_props.getProperty(name);
				if(cal == null){
					return defaultVal;
				}else{
					return val;
				}
			}
		}
	
	5、不完全单例类
		public class LazySingleton{
			private static LazySingleton m_instance = null;
			//公开的构造子
			public LazySingleton(){}
			
			public static synchronized LazySingleton getInstance(){
				if(m_instance == null){
					m_instance = new LazySingleton();
				}
				return m_instance;
			}
		}
	

6、相关模式:
1) 简单工厂模式:单例模式使用了简单工厂模式来提供自己的实例
最常见的目录服务包括LDAP和DNS————(命名—服务)将一个对象与一个名字联系起来,使得客户可以通过对象的名字找到这个对象
目录服务允许对象有属性,这样客户端通过查询找到对象后,可以进一步得到对象的属性,或者反过来根据属性查询对象

DNS————即域名服务,电脑用户在网络上找到其他的电脑用户必须通过域名服务。在国际网络以及任何一个建立在TCP/IP基础上的
网络上的,每一台电脑都有一个唯一的IP地址。

MX记录——就是邮件交换记录。电子邮件服务器记录指定一台服务器接受某个域名服务器的邮件,也就是说,发往jeffcorp.com 的邮
件将发往 mail.jeffcorp.com 的服务器,完成此任务的MX纪录应当像下面这样:
jeffcorp.com.IN MX 10 mail.jeffcorp.com
在上面的这个记录的最左边是国际网络上使用的电子邮件域名,第三列是一个数字10,它代表此服务器的优先权是10。通常来说,一个
大型的系统会有数台电子邮件服务器,这些服务器可以依照优先权作为候补服务器使用,优先权不需是一个正整数,这个数字越低,表明
优先权越高。

JNDI的全称是java命名和地址界面,其目的是为java系统提供支持各种目录类型的一个一般性的访问界面

JNDI架构由JNDI API 和 JNDI SPI组成。JNDI API使得一个java应用程序可以使用一系列的命名和目录服务。JNDI SPI是为服务提
供商,包括目录服务提供商准备的,它可以让各种命名和目录服务能够以对应用程序透明的方式插入到系统里。

JNDI API由以下四个库组成:
1) javax.naming: 包括了使用命名服务的类和接口。
2) javax.naming.directory: 扩展了核心库javax.naming的功能,提供目录访问功能。
3) javax.naming.event: 包括了命名和目录服务中所需要的时间同志机制的类和接口
4) javax.naming.ldap: 包括了命名和目录服务中支持LDAP(v3)所需要的类和接口
JNDI SPI的库为:
javax.naming.spi: 包括的类和接口允许各种的命名和目录服务提供商能将自己的软件服务构建加入到JNDI架构中去
在JNDI里,所有的命名和目录操作都是相对于某一个context(环境)而言,JNDI并没有任何的绝对根目录。JNDI定义一个初始环境对象
称为InitialContext,来提供命名和目录操作的起始点。一旦得到了初始环境,就可以使用初始环境查询其他环境和对象。
//MailServer
		public class MailServer{
			private int priority;
			private String server;
			//优先权的赋值方法
			public void setPriority(int priority){
				this.priority = priority;
			}
			//服务器名的赋值方法
			public void setServer(String server){
				this.server = server;
			}
			public int getPriority(){
				return priority;
			}
			public String getServer(){
				return server;
			}
		}
		
		//系统核心类(MXList)
		import java.util.Enumeration;
		import java.util.Hashtable;
		import java.util.Vector;
		import java.util.String.Tokenizer;
		import javax.naming.NamingEnumeration;
		import javax.naming.directory.DirContext;
		import javax.naming.directory.InitialDirContext;
		import javax.naming.directory.Attributes;
		import javax.naming.directory.Attribute;
		
		public class MXList{
			private static MXList mxl = null;
			private Vector list = null;
			private static final String FACTORY_ENTRY = "java.naming.factory.initial";
			private static final String FACTORY_CLASS = "com.sun.jndi.dns.DnsContextFactory";
			private static final String PROVIDER_ENTRY = "java.naming,provider.url";
			private static final String MX_TYPE = "MX";
			private String dnsUrl = null;
			private String domainName = null;
			
			private MXList(){}
			
			private MXList(String dnsUrl, String domainName) throws Exception{
				this.dnsUrl = dnsUrl;
				this.domainName = domainName;
				
				this.list = getMXRecords(dnsUrk, domainName);
			}
			
			//静态工厂方法
			public static synchronized MXList getInstance(String dnsUrl,String domainName) throws Exception{
				if(mxl == null){
					mxl = new MXList(dnsUrl, domainName);
				}
				return mxl;
			}
			//聚集方法,提供聚集元素
			public MailServer elementAt(int index) throws Exception{
				return (MailServer)list.elementAt(index);
			}
			//聚集方法,提供聚集大小
			public int size(){
				return list.size();
			}
			//辅助方法,向DNS服务器查询MX记录
			private Vector getMXRecords(String providerUrl, String domainName) throws Exception{
				//设置环境性质
				Hashtable env= new Hashtable();
				env.put(FACTORY_ENTRY, FACTORY_CLASS);
				env.put(PROVIDER_ENTRY, providerUrl);
				
				//创建环境对象
				DirContext dirContext = new InitialDirContext(env);
				
				Vector records = new Vector(10);
				
				//读取环境对象的属性
				Attributes attrs = dirContext.getAttributes(domainName,new String[]{MX_TYPE});
				
				for(NamingEnumeration ne = attrs.getAll(); ne != null && ne.hasMoreElements();){
					Attribute attr = (Attribute)ne.next();
					NamingEnumeration e = attr.getAll();
					while(e.hasMoreElements()){
						String element = e.nextElement().toString();
						StringTokenizer tokenizer = new StringTokenizer(element, "");
						
						MailServer mailServer = new MailServer();
						
						String token1 = tokenizer.nextToken();
						String token2 = tokenizer.nextToken();
						
						if(token1 != null && token2 != null){
							mailServer.setPriority(Integer.valueOf(token1).inValue());
							mailServer.setServer(token2);
							records.addElement(mailServer);
						}
					}
				}
				System.out.println("List created.");
				return records;
			}
			
		}
		
		//客户端类
		public class Client{
			private static MXList mxl;
			public static void main(String args[]) throws Exception{
				mxl = MXList.getInstance("dns://dns01390.ny.jeffcorp.com", "jeffcorp.com");
				
				for(int i = 0; i < mxl.size(); i ++){
					System.out.println((i + 1) + ") priority = " + ((MailServer)mxl.elementAt(i)).
					getPriority() + ", Name = " + ((MailServer)mxl.elementAt(i)).getServer());
				}
			}
		}
分享到:
评论

相关推荐

    singleTon单例模式的创建

    ### SingleTon单例模式的创建 #### 一、单例模式概述 单例模式是一种常用的软件设计模式,它确保一个类只有一个实例,并提供一个全局访问点。这种模式通常用于那些需要频繁实例化然后销毁的对象,或者创建对象需要...

    单例模式(singleton)

    实现单例模式的关键在于防止其他对象通过常规构造函数创建新的实例。这通常通过私有化构造函数和提供一个公共静态方法(称为单例工厂方法)来实现。在Java中,单例模式的实现有多种方式: 1. 饿汉式(Static ...

    Java 单例模式 工具类

    本篇文章将深入探讨如何在Java中实现单例模式,以及如何创建一个工具类来封装单例的创建。 首先,让我们了解单例模式的几种常见实现方式: 1. 饿汉式(静态常量): 这是最简单的单例实现,它在类加载时就完成了...

    Singleton pattern单例模式应用

    3. **延迟初始化**:单例模式通常会延迟实例化,直到第一次调用时才创建实例,这称为懒汉式加载。 #### 三、Java代码实现 在给定的部分内容中,虽然没有直接展示单例模式的实现,但我们可以基于其原理来构建一个...

    创建型模式之单例模式(Singleton Pattern)

    单例模式是软件设计模式中的一种,属于创建型模式,它的主要目的是确保一个类只有一个实例,并提供一个全局访问点。这种模式在很多场景下都非常有用,例如管理共享资源、配置对象或者缓存服务等。 单例模式的核心...

    单例模式(Singleton)的6种实现

    懒汉式单例模式延迟了单例实例的创建,直到第一次被引用时才创建。这种实现方式的优点是按需创建,节省资源。但是懒汉式在多线程环境下可能会产生多个实例,因此需要使用同步机制来解决多线程问题。 3. 双重检查...

    java Singleton单例模式

    接下来,我们将深入探讨Java Singleton模式的实现方式、优缺点以及使用场景。 一、Singleton模式的实现 1. 饿汉式(静态常量) ```java public class Singleton { private static final Singleton INSTANCE = ...

    单例设计模式.pdf

    单例设计模式是一种在软件设计中广泛使用的设计模式,它属于创建型模式,其核心目标是确保类只有一个实例,并提供一个全局访问点。这个模式在Java中尤其常见,因为Java的垃圾回收机制允许对象长时间驻留在内存中,...

    单例 singleton txt

    单例模式(Singleton Pattern)是一种常用的软件设计模式,属于创建型模式之一。其主要目的是确保一个类只有一个实例,并提供一个全局访问点来访问该实例。这在某些情况下非常有用,比如系统中需要频繁创建后又销毁...

    C#单例模式详解 C#单例模式详解C#单例模式详解

    单例模式是软件设计模式中的一种,它保证一个类只有一个实例,并提供一个全局访问点。在C#中,单例模式常用于管理共享资源或控制类的实例化过程,以提高性能、节约系统资源,特别是在整个应用程序生命周期内只需要一...

    单例 模式 singleton

    最基础的单例模式实现是"饿汉式",即在类加载时就创建实例。这种方式确保了在任何时刻只有一个实例存在,但同时也意味着即使单例未被使用,也会立即创建实例。示例如上文所示: ```java public class ...

    Singleton 单例模式的介绍以及解析

    如果不正确地实现单例模式,可能会导致多个线程同时创建类的实例,违反了单例模式的设计初衷。为了解决这个问题,我们可以采用以下几种策略: 1. **懒汉式(线程不安全)**:在首次调用时才初始化单例,但这种方式...

    几种单例模式demo

    单例模式是软件设计模式中的一种,它的主要目的是确保一个类只有一个实例,并提供一个全局访问点。这种模式在很多场景下都非常有用,比如控制资源的唯一性、管理共享配置或者创建昂贵的对象时避免频繁创建销毁。 ...

    Singleton单例模式.zip

    本资料包“Singleton单例模式.zip”提供的是C#实现单例模式的源代码示例。 单例模式的核心在于限制类的构造函数访问,防止外部代码随意创建实例。通常,我们通过以下几种方式来实现C#中的单例模式: 1. 饿汉式...

    设计模式之单例模式源码demo

    2. **懒汉单例模式**:延迟到第一次调用`getInstance()`方法时才进行实例化,这种实现方式解决了饿汉模式的内存浪费问题,但在多线程环境下不安全。 ```java public class Singleton { private static Singleton ...

    Java设计模式之单例模式的七种写法

    懒汉式单例是一种常见的单例模式实现方式,它在第一次调用的时候实例化自己。下面是懒汉式单例的四种写法: 1、基本懒汉式单例 public class Singleton1 { private Singleton1() {} private static Singleton1 ...

    单例模式.zip(c#设计模式)

    在《设计模式》第二版中,刘伟老师深入讲解了单例模式,本压缩包中的"单例模式习题6"和"单例模式习题7"可能是书中的课后练习,旨在帮助读者更好地理解和运用单例模式。 单例模式的核心思想是控制类的实例化过程,...

    Java面向对象(高级)- 单例(Singleton)设计模式

    - 懒汉式(Lazy Initialization):在第一次调用getInstance时才创建单例对象。如果不使用单例,就不会创建,节省资源。但线程不安全,需要通过同步机制保证。 ```java public class Singleton { private static ...

    单例模式代码.rar

    4. **双重检查锁定(DCL,线程安全)**:解决了懒汉式的线程安全问题,通过双重检查和同步来确保单例的正确创建。 ```java public class Singleton { private volatile static Singleton INSTANCE; private ...

Global site tag (gtag.js) - Google Analytics