该原创文章首发于微信公众号:字节流动
设计模式
设计模式简而言之就是优秀的代码设计经验的总结。设计模式的产生是为了提高代码的可复用性,可扩展性以及可靠性,但是往往会降低可读性。
设计模式原则
- 单一职责原则: 一个类只负责一项职责;
- 里氏替换原则: 子类可以扩展父类的功能,但不能改变父类原有的功能;
- 依赖倒置原则: 面向接口编程,将依赖对象的共同特征抽象成接口;
- 接口隔离原则: 一个类不应该实现它不需要的接口方法,即建立单一接口,细化接口,尽量减少接口中的方法;
- 迪米特法则: 一个对象应该对其他对象保持最少的了解,即降低类与类之间的耦合;
- 开闭原则: 一个类对扩展开放,对修改关闭。
设计模式分类
创建型设计模式
设计对象的实例化,避免用户用 new 运算符创建对象。例如单例模式,Builder 模式,原型模式等。
行为型设计模式
设计对象之间的通信交互。如观察者模式,迭代器模式,责任链模式等。
结构型设计模式
设计如何组合类和对象以形成更大的结构。如适配器模式,代理模式,桥接模式等。
单例模式
简单介绍常用的五种单例模式的写法。
饿汉式单例
public class Person {
private static final Person INSTANCE = new Person();
private Person(){
}
public static Person getInstance() {
return INSTANCE;
}
}
优点:线程安全。
缺点:类加载的时候就进行初始化,对于初始化逻辑复杂的类,会导致类加载变慢。
(DCL) 懒汉式单例
public class Person {
private static volatile Person sInstance = null;
private Person(){
}
public static Person getInstance() {
if (sInstance == null){
synchronized (Person.class) {
if (sInstance == null) {
sInstance = new Person();
}
}
}
return sInstance;
}
}
优点:volatile 声明单例引用,可以防止并发时初始化成员变量和对象实例化顺序可能会被打乱,双重检查锁定解决了多余的同步问题。
缺点:JVM 创建一个对象会执行 3 个原子操作,在高并发时仍存在极小的概率导致 DCL 失效。
静态内部类单例
public class Person {
private Person(){
}
private static class Singleton {
private static final Person INSTANCE = new Person();
}
public static Person getInstance() {
return Singleton.INSTANCE;
}
}
优点:充分结合了懒汉式单例与饿汉式的优点,同时有效避开了它们的缺点,充分保证线程安全。推荐
缺点:会有的!
枚举型单例
public enum PersonEnum {
INSTANCE;
private PersonEnum() {
}
public void fun() {
// do something
}
}
使用方法:
PersonEnum.INSTANCE.fun();
优点:简洁,线程安全。
《Effective Java》的作者在书中是这样夸枚举型单例:
这种写法在功能上与共有域方法相近,但是它更简洁,无偿地提供了序列化机制,绝对防止对此实例化,即使是在面对复杂的序列化或者反射攻击的时候。
虽然这中方法还没有广泛采用,但是单元素的枚举类型已经成为实现Singleton的最佳方法。
缺点:Google 官方强烈建议尽量不要使用 enum ,它会增加额外的内存占用,同时增加可执行文件 .dex 的大小,也不适用继承场景。
容器型单例
public class Person {
public Person () {
}
}
public class SingletonManager {
public static final KEY_SINGLETON = "singleton";
private static Map<String, Object> sInstanceMap = new HashMap<>();
public static void registerSingleton(String key, Object obj) {
if (!sInstanceMap.containsKey(key)) {
sInstanceMap.put(key, obj);
}
}
public static Person getSingleton(String key) {
return (Person) sInstanceMap.get(key);
}
}
使用:
SingletonManager.registerSingleton(KEY_SINGLETON, new Person);
Person person = SingletonManager.getSingleton();
优点:可以将不同单例注册到一个容器中统一管理,隐藏了类的具体实现,降低了耦合度。推荐
缺点:会有的!
单例模式的优点与缺点
优点:减少内存开销,避免资源重用。
缺点:单例类的扩展性很差,持有外部引用时,非常容易造成内存泄漏。
联系与交流
我的公众号
我的微信