单例模式的九种实现 & 组合模式练习

单例模式的九种五种实现
懒汉&饿汉
饿汉的缺点在于不支持延迟加载,这里我觉得如果单例加载时间长的话反而应该在启动的时候加载,如果运行时加载反而影响体验,本末倒置。
懒汉优点是支持延迟加载,缺点是getInstance方法使用了锁导致性能一般。

双重检查
上面讲了懒汉式因为使用锁而导致并发条件下的性能问题,双重检查可以通过细粒度锁只在创建instance的时候加锁从而规避性能问题。
这里需要注意:
在J2SE 1.4或更早的版本中使用双重检查锁有潜在的危险,有时会正常工作:区分正确实现和有小问题的实现是很困难的。取决于编译器,线程的调度和其他并发系统活动,不正确的实现双重检查锁导致的异常结果可能会间歇性出现。重现异常是十分困难的。
在J2SE 5.0中,这一问题被修正了。volatile关键字保证多个线程可以正确处理单件实例。

静态内部类&枚举
静态内部类利用了jvm类加载的机制,实现了延迟加载。即只有调用getInstance才会加载静态内部类创建实例,创建实例也通过jvm来控制。
枚举的写法非常简单。

组合模式
项目仓库:
https://github.com/wuyueandrew/designpattern1
这个实现比较简单,GUINode接口声明一个打印节点和子节点的方法,每个节点都必须实现。WinForm和Frame类里都有子节点的容器。入口类是BasicApplication,输出如下:

评论