JavaMe 编程连载(9) - 重构之数据永久存储

【更新】

2012-6-3

更新【代码重构】

2012-6-2

(1) 修复getDataByIndex、getDataByName潜在bug

(2) 添加代码重构栏目,后续更新将补充完整

 

【问题描述】在JavaMe 编程连载(7) - 数据永久存储一文结尾,提到了构建通用数据库的思路。最近,在阅读《重构-改善既有代码的设计》,感觉刚开始写的数据永久存储代码比较丑陋。一时技痒。写了一个通用的数据永久存储。分享一下代码和思路。

 

【代码清单】

原来的代码就不列了,详细请参考JavaMe 编程连载(7) - 数据永久存储一文。

DataItem.java(update:2012-6-2)

package com.token.model;

import com.token.util.StringMethod;

public class DataItem {
	private int id;
	private String args_t[][];
	private Object[] args;
	private int length;

	public DataItem(int id, Object[] args) {
		this.id = id;
		this.args = args;
		length = args.length;
		args_t = new String[args.length][2];

		for (int i = 0; i < args.length; i++) {
			args_t[i] = StringMethod.split((String) args[i], "=");
			// System.out.println(args_t[i][0]);
			// System.out.println(args_t[i][1]);
		}
	}

	public DataItem(int id, String data) {
		// System.out.println(data);

		String temp[] = StringMethod.split(data, ",");
		this.id = id;
		this.args = temp;
		length = temp.length;

		args_t = new String[temp.length][2];

		for (int i = 0; i < temp.length; i++) {
			args_t[i] = StringMethod.split(temp[i], "=");
			// System.out.println(args_t[i][0]);
			// System.out.println(args_t[i][1]);
		}
	}

	public DataItem(int id, byte[] record) {
		// TODO Auto-generated constructor stub
		this.id = id;
		String temp = new String(record);
		System.out.println(temp);
	}

	public int getId() {

		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public int getDataLength() {
		return length;
	}

	public String getDataByIndex(int index) {
		if(index<getDataLength())
		{
			return args_t[index][1];
		}
		else
		{
			return "";
		}
	}

	public String getDataByName(String name) {
		int index = -1;

		int i;
		for (i = 0; i < getDataLength(); i++) {
			if (args_t[i][0].equals(name)) {
				index = i;
				break;
			}
		}
		
		if(index != -1)
		{
			return args_t[index][1];
		}
		else
		{
			return "";
		}
		
	}

	public byte[] getBytes() {
		String data = "";

		for (int i = 0; i < args.length; i++) {
			data += (String) args[i];
			data += ",";
		}

		data = data.substring(0, data.length() - 1);
		// System.out.println(data);

		return data.getBytes();
	}
}


 DataRecord.java

package com.token.util;

import java.util.Vector;

import javax.microedition.rms.RecordComparator;
import javax.microedition.rms.RecordEnumeration;
import javax.microedition.rms.RecordStore;
import javax.microedition.rms.RecordStoreException;

import com.token.model.DataItem;

public class DataRecord {
	private RecordStore record;
	private String dataBaseName;

	public DataRecord(String name) {
		dataBaseName = name;
	}

	protected String getDataBaseName() {
		// System.out.println(dataBaseName);
		return dataBaseName;
	}

	// 打开RecordStore
	public void openDataBase() {
		String name = getDataBaseName();
		try {
			record = RecordStore.openRecordStore(name, true);
		} catch (RecordStoreException ex) {
			record = null;
			System.out.println(ex);
		}
	}

	// 关闭RecordStore
	public void closeDataBase() {
		if (record != null) {
			try {
				record.closeRecordStore();
				record = null;
			} catch (RecordStoreException ex) {
				System.out.println(ex);
			}
		}
	}

	// 增加记录
	public int db_addRecord(DataItem item) {
		try {
			this.openDataBase();
			byte[] data = item.getBytes();
			int id = record.getNextRecordID();
			record.addRecord(data, 0, data.length);
			this.closeDataBase();
			return id;
		} catch (RecordStoreException ex) {
			System.out.println(ex);
		}

		return -1;
	}

	// 更新记录
	public void db_updateRecord(DataItem item) {
		try {
			this.openDataBase();
			byte[] data = item.getBytes();
			record.setRecord(item.getId(), data, 0, data.length);
			this.closeDataBase();
		} catch (RecordStoreException ex) {
			System.out.println(ex);
		}
	}

	// 访问一条记录
	public DataItem db_getRecord(int id) {
		DataItem item = null;

		try {
			this.openDataBase();
			byte data[] = record.getRecord(id);

			item = new DataItem(id, new String(data));
			this.closeDataBase();
		} catch (RecordStoreException ex) {
			// System.out.println(ex);
		}

		return item;
	}

	// 删除一条记录
	public void db_deleteRecord(int id) {
		try {
			this.openDataBase();
			record.deleteRecord(id);
			this.closeDataBase();
		} catch (RecordStoreException ex) {
			System.out.println(ex);
		}
	}

	// 删除所有记录
	public void db_deleteAllRecord() {
		try {
			RecordStore.deleteRecordStore(getDataBaseName());
		} catch (RecordStoreException ex) {
			System.out.println(ex);
		}
	}

	// 访问所有记录
	public Vector db_getRecords() {
		Vector items = new Vector(10, 3);
		this.openDataBase();// 打开RecordStore
		RecordEnumeration enum1 = null;
		int ind = 0;
		try {
			DataItem item = null;
			enum1 = record.enumerateRecords(null, new InnerComparator(), false);

			while (enum1.hasPreviousElement()) {
				ind = enum1.previousRecordId();
				item = new DataItem(ind, record.getRecord(ind));
				items.addElement(item);
			}

		} catch (Exception ex) {
			ex.printStackTrace();
		} finally {
			try {
				enum1.destroy();
			} catch (Exception e) {
			}

			this.closeDataBase();// 关闭RecordStore
		}// end finally

		return items;
	}

	// 一个简单的比较器
	private class InnerComparator implements RecordComparator {
		public int compare(byte[] rec1, byte[] rec2) {
			if (rec1.length > rec2.length)
				return FOLLOWS;
			else if (rec1.length < rec2.length)
				return PRECEDES;
			else
				return EQUIVALENT;
		}

	}

	public static class DataBaseName {
		public static final String DB_TEST = "test";
	}
}


StringMethod.java

package com.token.util;

import java.util.Vector;

import javax.microedition.lcdui.Font;

public class StringMethod {
	StringMethod() {

	}

	// 字符串切割,实现字符串自动换行
	public static String[] format(String text, int maxWidth, Font ft) {
		String[] result = null;
		Vector tempR = new Vector();
		int lines = 0;
		int len = text.length();
		int index0 = 0;
		int index1 = 0;
		boolean wrap;
		while (true) {
			int widthes = 0;
			wrap = false;
			for (index0 = index1; index1 < len; index1++) {
				if (text.charAt(index1) == '\n') {
					index1++;
					wrap = true;
					break;
				}
				widthes = ft.charWidth(text.charAt(index1)) + widthes;

				if (widthes > maxWidth) {
					break;
				}
			}
			lines++;

			if (wrap) {
				tempR.addElement(text.substring(index0, index1 - 1));
			} else {
				tempR.addElement(text.substring(index0, index1));
			}
			if (index1 >= len) {
				break;
			}
		}
		result = new String[lines];
		tempR.copyInto(result);
		return result;
	}

	public static String[] split(String original, String separator) {
		Vector nodes = new Vector();
		// System.out.println("split start...................");
		// Parse nodes into vector
		int index = original.indexOf(separator);
		while (index >= 0) {
			nodes.addElement(original.substring(0, index));
			original = original.substring(index + separator.length());
			index = original.indexOf(separator);
		}
		// Get the last node
		nodes.addElement(original);

		// Create splitted string array
		String[] result = new String[nodes.size()];
		if (nodes.size() > 0) {
			for (int loop = 0; loop < nodes.size(); loop++) {
				result[loop] = (String) nodes.elementAt(loop);
				// System.out.println(result[loop]);
			}

		}

		return result;
	}
}

 

测试代码(update:2012-6-2)

public void test() {
		DataRecord record = new DataRecord("test");
		//DataRecord record = new DataRecord(DataRecord.DataBaseName.DB_TEST);

		// delete all
		record.db_deleteAllRecord();
		// add
		DataItem item1 = new DataItem(1, "name=zhang,x=1,y=2,z=3");
		int id = record.db_addRecord(item1);
		System.out.println("id:"+id);
		DataItem item = record.db_getRecord(id);
		System.out.println("z:" + item.getDataByName("z") + "(getbyname)");
		System.out.println("y:" + item.getDataByIndex(2) + "(getbyindex)");
		System.out.println("test u:" + item.getDataByName("u") + "(getbyname)");//越界
		System.out.println("test:" + item.getDataByIndex(4) + "(getbyindex)");//越界
		// add
		Object[] data1 = { "name=liu,x=4,y=5,z=6" };
		DataItem item2 = new DataItem(1, data1);
		id = record.db_addRecord(item2);
		System.out.println("id:"+id);
		record.db_getRecords();
		// update
		Object[] data2 = { "name=li,x=7,y=8,z=9" };
		DataItem item3 = new DataItem(id, data2);
		record.db_updateRecord(item3);
		item = record.db_getRecord(id);
		System.out.println("x:" + item.getDataByName("x"));
		// delete
		record.db_deleteRecord(id);
		record.db_getRecords();

	}


 


【分析】

1 该通用数据永久存储提供了两种数据格式:

(1) 传递Object []对象

Object[] data2 = { "name=li,x=7,y=8,z=9" };
		DataItem item3 = new DataItem(id, data2);


(2) 传递String

DataItem item1 = new DataItem(1, "name=zhang,x=1,y=2,z=3");


数据采用key=value的形式进行存储,以“,”分隔键值对。

 

2 实现了增、改、删、查

(1) 增

DataItem item1 = new DataItem(1, "name=zhang,x=1,y=2,z=3");
		int id = record.db_addRecord(item1);


(2) 改

Object[] data2 = { "name=li,x=7,y=8,z=9" };
		DataItem item3 = new DataItem(id, data2);
		record.db_updateRecord(item3);


(3) 删

delete all

record.db_deleteAllRecord();

delete by id

record.db_deleteRecord(id);

 

(4) 查

get all

record.db_getRecords();

get record by id

DataItem item = record.db_getRecord(id);
System.out.println("x:" + item.getDataByName("x") + "(getbyname)");
System.out.println("y:" + item.getDataByIndex(2) + "(getbyindex)");


3 提供了两种数据访问方式

(1) 按键(key)访问

System.out.println("x:" + item.getDataByName("x") + "(getbyname)");

 

(2) 按索引访问

*第1个数据索引为0,依次类推

System.out.println("y:" + item.getDataByIndex(2) + "(getbyindex)");


4 如何使用

在构造对象时,传入记录名作为区分,该名称为记录唯一标识,提供访问记录接口

DataRecord record = new DataRecord("test");

为了在不同文件中使用,防止出错,在DataRecord.java中建了一个内部类,存储记录名

public static class DataBaseName {
		public static final String DB_TEST = "test";
	}

每次调用可采用如下方式:

DataRecord record = new DataRecord(DataRecord.DataBaseName.DB_TEST);


 

5 拓展

可以将DataItem和DataRecord做为基类,采用装饰模式,进行包装,使用更简便。

 

 【代码重构】(2012-6-2)

1 去掉分支结构

在代码清单中,下面一段还是比较丑陋

public String getDataByIndex(int index) {
		if(index<getDataLength())
		{
			return args_t[index][1];
		}
		else
		{
			return "";
		}
	}

	public String getDataByName(String name) {
		int index = -1;

		int i;
		for (i = 0; i < getDataLength(); i++) {
			if (args_t[i][0].equals(name)) {
				index = i;
				break;
			}
		}
		
		if(index != -1)
		{
			return args_t[index][1];
		}
		else
		{
			return "";
		}
		
	}


运用去除分支结构的方法,重构后,

public String getDataByIndex(int index) {
		
		//System.out.println(index);
		return index < getDataLength() ? args_t[index][1] : "";
	}

	public String getDataByName(String name) {
		int index = -1;

		int i;
		for (i = 0; i < getDataLength(); i++) {
			if (args_t[i][0].equals(name)) {
				index = i;
				break;
			}
		}
		//System.out.println(index);
		
		return index != -1 ? args_t[index][1] : "";

		
	}


 

2 Singleton模式的思考

JavaMe 编程连载(7) - 数据永久存储代码相比,有一处很细微的重构,但不得不提。

private RecordStore record;
private String dataBaseName;

重构前的代码为:

private static RecordStore record;
private static String dataBaseName;

代码去掉了static关键字。在通用版本中,不能添加该关键字。原因是添加static关键字后,实例存储在一个固定的区域,同一工程中只存在一个实例。在工程中,如果使用多个记录,由于只能存在一个实例,会无法区分记录,造成混乱。Singleton模式请参考设计模式之二 --- Singleton 模式。

 

 

 

 *在Eclipse中可利用ctrl+shift+F进行自动排版

 

 

转载请标明出处,仅供学习交流,勿用于商业目的

Copyright @ http://blog.csdn.net/tandesir

 

 

 

 

 
 
 

你可能感兴趣的:(JavaMe 编程连载(9) - 重构之数据永久存储)