首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件开发 >

[知识点] 漫话设计模式 03

2012-09-20 
[知识点] 漫谈设计模式 03第二篇 创建对象- 直接使用new 所带来的高耦合度。- 如何避免耦合度?- OOP带给我

[知识点] 漫谈设计模式 03

第二篇 创建对象

- 直接使用new 所带来的高耦合度。

- 如何避免耦合度?

- OOP带给我们的好处之一是封装,如果封装这些实例化的细节,即对客户对象隐藏实例化的过程,

?那么我们新添加一个接口的实现或者抽象类的具体类,也不会影响客户代码了,降低了耦合度。

- 客户对象(Client)和服务对象(Service) -->可移植性和重用性

-- Chapter 3: 单例模式【Singleton】

-> 如何保证一个类在一个系统里面只有一个实例?

-- Chapter 4: 工厂方法模式【Factory method】

-> 如何实例化对象使得对象和使用者之间的耦合度降低?

-- Chapter 5: 原型模式【Prototype】

-> 如何拷贝现有的对象快速的创建一个新的复杂对象?

-- Chapter 6: 控制反转【IoC】

-> IoC和依赖注入DI ?Inverse of contrale

# 3.1 概述

- 一个系统里只有一个类

- 常见:缓存池,数据库连接池,线程池,一些应用服务实例等

- 在多线程的环境中,为了保证实例的唯一性实则不易

# 3.2 最简单的实例

- 该类的构造方法是私有的(外部类无法创建)

- 提供一个全局访问点

- [code]

public class Singleton {

private static Singleton instance = new Singleton(); //外界无法访问

private Singleton() { //客户对象无法创建

}

public static Singleton getInstance () { //全局访问点

return instance;

}

}

? [code]

注意 1. instance没有直接暴露给外界

?2. 此实现是线程安全,当多个线程同时去访问该类的getInstance方法时,不会初始化多个对象,

? ? 因为JVM在加载此类时,对于static属性的初始化只能由一个线程执行且仅一次。

? ? ?3. 客户端使用简便: Singleton singleton = Singleton.getInstance();

# 3.3 进阶

## 3.3.1 迟延创建

- 只有在第一次使用该类的实例化时才去实例化。

->> 把单例的实例化个过程移至getInstance方法即可,而不是在加载类时预先创建。

- [code]

public class UnThreadSaftSingleton {

private UnThreadSaftSingleton instance;

public static UnThreadSaftSingleton getInstance () {

if (instance == null) {

instance = new UnThreadSaftSingleton();

}

return instance;

}

}

[code]

## 3.3.2 线程安全

注意: 1. 高并发环境中,线程不安全的,会产生多个指向该类的实例,并出现内存泄漏的情况。

2. 解决该问题,只需要对getInstance方法加 synchronized 关键字。

## 3.3.3 Double-Check Locking

- synchronized 性能有问题 --> 对整个getInstance方法进行同步是没有必要的

- 只要保证被实例化的那段逻辑被一个线程执行就OK了,而返回引用的那段代码则没必要同步

[code]?

public class DoubleCheckSingleton {

private valotile static DoubleCheckSingleton instance = null;

public static DoubleCheckSingleton getInstance () {

if(instance == null) {

synchronized(DoubleCheckSingleton.class) { //synchronize creation block

if (instance == null) {

instance = new DoubleCheckSingleton();

}

}

}

return instance;

}

}

[code]

注意: 1. 锁住初始化代码块

2. 两次判断,故称 Double checked Locking

3. 属性instance是被volatile修饰的。 作用:线程能够自动发现volatile变量的最新值

4. 此程序只有在Java 5 及以上版本才能运行

## 3.3.4 Initialization on demand holder

- 另一种实现线程安全的单例模式

[code]

public class LazyLoadedSingleton {

private LazyLoaderSingleton () {

}

private static class LazyHolder {

private static final LazyLoadedSingleton singletonInstance =?

new LazyLoadedSingleton();

}

public static LazyLoadedSingleton getInstance () {

return LazyHolder.singletonInstance;

}

}

[code]

注意:只有第一调用 getInstance 时才会加载。

## 3.3.5 Singleton的序列化

- 如果Singleton实现了Serializable接口,特别需要注意:

在默认情况下,每次反序列化总会创建一个新的实例对象,这样一个系统就会出现多个对象可供使用。

- 需要在readResolve method 里面做文章

[code]

public class SerialibleSingleton implements Serializable {

private static final long serialVersionUID = 1L;

static SerialibleSingleton instance = new SerialibleSingleton();

private SerialibleSingleton(){

}

//This method is called immediately after an object of this class deserialized.

//This method return the singleton instance.

private Object readResolve () {

return instance;

}

}

[code]

- 这样内存中始终保存一个对象

# 3.5 总结

- 基于同一个Jvm中,如何保证一个类只有一个实例

- 如果在分布式环境中,可能需要考虑如何保证在整个应用(可能分布在不同的JVM上)只有一个实例。

?

==思路清晰,简单易懂,又不失深度,好书==

?

热点排行