之前看过<< Head Frist 设计模式>>一书,对设计模式略有了解,但不清楚真实的Java中是怎么用到的.<< java与模式>>这本书很长,讲的非常详细,这里只摘抄了书中的例子,以此作为笔记学习.
1.工厂模式
1.1 DateFormat
public abstract class DateFormat extends Format {
DateFormat是一个抽象类,但它有静态工厂方法,如下:
private static DateFormat get(int timeStyle, int dateStyle,
int flags, Locale loc) {
if ((flags & 1) != 0) {
if (timeStyle < 0 || timeStyle > 3) {
throw new IllegalArgumentException("Illegal time style " + timeStyle);
}
} else {
timeStyle = -1;
}
if ((flags & 2) != 0) {
if (dateStyle < 0 || dateStyle > 3) {
throw new IllegalArgumentException("Illegal date style " + dateStyle);
}
} else {
dateStyle = -1;
}
try {
// Check whether a provider can provide an implementation that's closer
// to the requested locale than what the Java runtime itself can provide.
LocaleServiceProviderPool pool =
LocaleServiceProviderPool.getPool(DateFormatProvider.class);
if (pool.hasProviders()) {
DateFormat providersInstance = pool.getLocalizedObject(
DateFormatGetter.INSTANCE,
loc,
timeStyle,
dateStyle,
flags);
if (providersInstance != null) {
return providersInstance;
}
}
return new SimpleDateFormat(timeStyle, dateStyle, loc);
} catch (MissingResourceException e) {
return new SimpleDateFormat("M/d/yy h:mm a");
}
}
该方法最后返回一个SimpleDateFormat实例,并且将它声明为DateFormat类型.这是纯正的多态性的运用.
一个中文日期的例子:
@Test
public void simpleFactory(){
Locale locale = Locale.CHINA;
Date date = new Date();
String now = DateFormat.getDateInstance(DateFormat.DEFAULT, locale)
.format(date);
System.out.println(now);
}
返回结果如下:
2015-11-27
1.2 URL与URLConnection
public final class URL implements java.io.Serializable {
transient URLStreamHandler handler;
public URLConnection openConnection() throws java.io.IOException {
return handler.openConnection(this);
}
}
URL对象使用了工厂方法模式,以一个工厂方法openConnection()返回一个URLCollection类型的对象.由于URLConnection是一个抽象类,因此返回的是其具体子类的实例.
handler的初始化方法在URL初始化阶段.
一个访问CSDN的例子:
@Test
public void factory() throws IOException{
URL baidu = new URL("http://www.csdn.com");
URLConnection yc = baidu.openConnection();
BufferedReader in = new BufferedReader(
new InputStreamReader(
yc.getInputStream()));
String inputLine;
while((inputLine = in.readLine()) != null)
System.out.println(inputLine);
in.close();
}
返回结果如下:
<!DOCTYPE HTML>
<html>
<head>
<script id="allmobilize" charset="utf-8" src="http://a.yunshipei.com/csdnnet/allmobilize.min.js"></script>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>CSDN.NET - 全球最大中文IT社区,为IT专业技术人员提供最全面的信息传播和服务平台</title>
<link href="http://c.csdnimg.cn/www/css/csdn_common.css" rel="stylesheet" type="text/css">
<link href="css/content.css" rel="stylesheet" type="text/css">
<link href="http://c.csdnimg.cn/public/favicon.ico" rel="SHORTCUT ICON">
...
...
...
...
2.单例模式
2.1 Properties
属性是系统的一种”资源”,应当避免有多于一个的对象读取,特别是存储属性.此外,属性的读取可能会在很多地方发生,创建属性对象的地方应当在哪里不是很清楚.换言之,属性管理器应当自己创建自己的实例,并且自己向系统全程提供这一实例.
因此,属性管理器应当是由一个单例模式负责的.
properties首先要知道去哪里找key-value键值对,load方法如下:
public synchronized void load(InputStream inStream) throws IOException {
load0(new LineReader(inStream));
}
private void load0 (LineReader lr) throws IOException {
char[] convtBuf = new char[1024];
int limit;
int keyLen;
int valueStart;
char c;
boolean hasSep;
boolean precedingBackslash;
while ((limit = lr.readLine()) >= 0) {
c = 0;
keyLen = 0;
valueStart = limit;
hasSep = false;
//System.out.println("line=<" + new String(lineBuf, 0, limit) + ">");
precedingBackslash = false;
while (keyLen < limit) {
c = lr.lineBuf[keyLen];
//need check if escaped.
if ((c == '=' || c == ':') && !precedingBackslash) {
valueStart = keyLen + 1;
hasSep = true;
break;
} else if ((c == ' ' || c == '\t' || c == '\f') && !precedingBackslash) {
valueStart = keyLen + 1;
break;
}
if (c == '\\') {
precedingBackslash = !precedingBackslash;
} else {
precedingBackslash = false;
}
keyLen++;
}
while (valueStart < limit) {
c = lr.lineBuf[valueStart];
if (c != ' ' && c != '\t' && c != '\f') {
if (!hasSep && (c == '=' || c == ':')) {
hasSep = true;
} else {
break;
}
}
valueStart++;
}
String key = loadConvert(lr.lineBuf, 0, keyLen, convtBuf);
String value = loadConvert(lr.lineBuf, valueStart, limit - valueStart, convtBuf);
put(key, value);
}
该方法将key-value储存在table中(该table继承自Hashtable).
2.2 Runtime
public class Runtime {
private static Runtime currentRuntime = new Runtime();
public static Runtime getRuntime() {
return currentRuntime;
}
}
很明显,RunTime类是采用”饿汉”方式实现的.