单例模式应用【创建模式第八篇】

预定式存储:

为了保证在任何情况下键值都不会出现重复,应当使用预定式键值存储办法。在请求一个键值时,首先将数据库中的键值更新为下一个可用值,

然后将旧值提供给客户端。这样万一出现运行中断的话,最多就是这个键值被浪费掉。

记录式存储:

键值首先被返还给客户端,然后记录到数据库中。这样做的缺点是,一旦系统中断,就有可能出现客户端已经使用了一个键值,而这个键值却

没有来得及存储到数据库中的情况。在系统重启后,系统还会从这个已经被使用过的键值开始,从而导致错误。

单例模式应用:序列键管理器

方案一:没有数据库的情况
	//序列键生成器(单例类)
	public class KeyGenerator{
		private static KeyGenerator keygen = new KeyGenerator();
		private int key = 1000;
		
		private KeyGenerator(){}
		
		//静态工厂方法,提供自己的实例
		public static KeyGenerator getInstance(){
			return keygen;
		}
		//取值方法,提供一个合适的键值
		public synchronized int getNextKey(){
			return key ++;
		}
	}
	
	//客户端
	public class Client{
		private static KeyGenerator keygen;
		
		public static void main(String args[]){
			keygen = KeyGenerator.getInstance();
			System.out.println("Key = " + keygen.getNextKey());
			System.out.println("Key = " + keygen.getNextKey());
			System.out.println("Key = " + keygen.getNextKey());
		}
	}
	//当系统重启时,计数就要重新开始
	
方案二:有数据库的情况:
	//序列键生成器(单例类)
	public class KeyGenerator{
		private static KeyGenerator keygen = new KeyGenerator();
		private int key = 1000;
		
		private KeyGenerator(){}
		
		//静态工厂方法,提供自己的实例
		public static KeyGenerator getInstance(){
			return keygen;
		}
		//取值方法,提供一个合适的键值
		public synchronized int getNextKey(){
			return getNextKeyFromDB();
		}
		
		private int getNextKeyFromDB(){
			String sql1 = "UPDATE KeyTable SET keyValue = keyValue + 1";
			String sql2 = "SELECT keyValue FROM KeyTable";
			//execute the update SQL
			//run the select query
			//示意性的返还一个数值
			return 1000;
		}
	}
	//每次都向数据库查询键值,将这个键值登记到表里,然后将查询结果返还给客户端
	
方案三:键值的缓存方案
	//序列键生成器(单例类)
	public class KeyGenerator{
		private static KeyGenerator keygen = new KeyGenerator();
		private static final int POOL_SIZE = 20;		//用于缓存20条记录
		private KeyInfo key;
		
		private KeyGenerator(){
			key = new KeyInfo(POOL_SIZE);
		}
		
		//静态工厂方法,提供自己的实例
		public static KeyGenerator getInstance(){
			return keygen;
		}
		//取值方法,提供一个合适的键值
		public synchronized int getNextKey(){
			return key.getNextKey();
		}
	}
	
	//KeyInfo类
	public class KeyInfo{
		private int keyMax;
		private int keyMin;
		private int nextKey;
		private int poolSize;
		
		public KeyInfo(int poolSize){
			this.poolSize = poolSize;
			retrieveFromDB();				//retrieve(检索)
		}
		
		//取值方法,提供键的最大值
		public int getKeyMax(){
			return keyMax;
		}
		
		public int getKeyMin(){
			return keyMin;
		}
		
		//取值方法,提供键的当前值
		public int getNextKey(){
			if(nextKey > keyMax){
				retrieveFromDB();
			}
			return nextKey ++;
		}
		
		//内部方法,从数据库提取键的当前值
		private void retrieveFromDB(){
			String sql1 = "UPDATE KeyTable SET keyValue = keyValue +" + poolSize + 
			"WHERE keyName = 'PO_NUMBER'";
			
			String sql2 = "SELECT keyValue FROM KeyTable WHERE keyName = 'PO_NUMBER'";
			//execute the above queries in a transaction and commit it		//commit提交/委托
			//assume the value returned is 1000					//assume假设
			int keyFromDB = 1000;
			keyMax = keyFromDB;
			keyMin = keyFromDB - poolSize + 1;
			nextKey = keyMin;
		}
	}
	
	//客户端
	public class Client{
		private static KeyGenerator keygen;
		
		public static void main(String args[]){
			keygen = KeyGenerator.getInstance();
			for(int i = 0; i < 20; i ++){
				System.out.println("Key(" + (i+1) + ")=" + keygen.getNextKey());
			}
		}
	}
	
方案四:有缓存的多序列键生成器
	//KeyGenerator
	import java.util.HashMap;
	
	public class KeyGenerator{
		private static KeyGenerator keygen = new KeyGenerator();
		private static final int POOL_SIZE = 20;
		private HashMap keyList = new HashMap(10);
		
		private KeyGenerator(){
			
		}
		
		public static KeyGenerator getInstance(){
			return keygen;
		}
		
		public synchronized int getNextKey(String keyName){
			KeyInfo keyInfo;
			if(keyList.containsKey(keyName)){
				keyInfo = (KeyInfo)keyList.get(keyName);
				System.out.println("Key found");
			}else{
				keyInfo = new KeyInfo(POOL_SIZE,keyName);
				keyList.put(keyName,keyInfo);
				System.out.println("New key created");
			}
			return keyInfo.getNextKey(keyName);
		}
	}
	
	//KeyInfo类
	public class KeyInfo{
		private int keyMax;
		private int keyMin;
		private int nextKey;
		private int poolSize;
		private String keyName;
		
		public KeyInfo(int poolSize,String keyName){
			this.poolSize = poolSize;
			this.keyName = keyName;
			retrieveFromDB();				//retrieve(检索)
		}
		
		//取值方法,提供键的最大值
		public int getKeyMax(){
			return keyMax;
		}
		
		public int getKeyMin(){
			return keyMin;
		}
		
		//取值方法,提供键的当前值
		public int getNextKey(){
			if(nextKey > keyMax){
				retrieveFromDB();
			}
			return nextKey ++;
		}
		
		//内部方法,从数据库提取键的当前值
		private void retrieveFromDB(){
			String sql1 = "UPDATE KeyTable SET keyValue = keyValue +" + poolSize + 
			"WHERE keyName = " + keyName + "";
			
			String sql2 = "SELECT keyValue FROM KeyTable WHERE keyName = " + keyNAme + "";
			//execute the above queries in a transaction and commit it		//commit提交/委托
			//assume the value returned is 1000					//assume假设
			int keyFromDB = 1000;
			keyMax = keyFromDB;
			keyMin = keyFromDB - poolSize + 1;
			nextKey = keyMin;
		}
	}
	
	//客户端
	public class Client{
		private static KeyGenerator keygen;
		
		public static void main(String args[]){
			keygen = KeyGenerator.getInstance();
			for(int i = 0; i < 20; i ++){
				System.out.println("Key(" + (i+1) + ")=" + keygen.getNextKey("PO_NUMBER"));
			}
		}
	}273P
	
方案五:多例模式
	//KeyGennerator
	import java.util.HashMap;
	public class KeyGenerator{
		private static HashMap Kengens = new HashMap(10);
		private static final int POOL_SIZE = 20;
		private KeyInfo keyinfo;
		
		private KeyGenerator(){}
		
		private KeyGenerator(String keyName){
			keyinfo = new KeyInfo(POOL_SIZE,keyName);
		}
		
		public static synchronized KeyGenerator getInstance(String keyName){
			KeyGenerator keygen;
			if(kengens.containsKey(keyName)){
				keygen = (KeyGenerator)kengens.get(keyName);
			}else{
				keygen = new KeyGenerator(keyName);
			}
			return keygen;
		}
		
		public synchronized int getNextKey(){
			return keyinfo.getNextKey();
		}
		//KeyInfo类与方案四里的相同
	}
	
	//客户端
	public class Client{
		private static KeyGenerator keygen;
		
		public static void main(String args[]){
			keygen = KeyGenerator.getInstance("PO_NUMBER");
			for(int i = 0; i < 20; i ++){
				System.out.println("Key(" + (i+1) + ")=" + keygen.getNextKey());
			}
		}
	}

相关推荐