前言
什么是设计模式?
设计模式是面向对象编程中的一种解决问题的方案或方法,它提供了一种在特定情况下进行软件设计的最佳实践,能够提高软件在可维护性、可重用性、可扩展性、可读性和可靠性等方面的质量和效率。设计模式是经过实践验证的,被广泛应用的在面向对象编程中的解决方案。根据功能和特性的不同,设计模式可分为三类:
-
创建型模式:用于对象的创建,包括单例模式、工厂模式、抽象工厂模式、建造者模式和原型模式等。
-
结构型模式:用于对象和类之间的组织关系,包括适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式和享元模式等。
-
行为型模式:用于描述对象和类之间的通信关系,包括观察者模式、模板方法模式、命令模式、状态模式、职责链模式、策略模式、访问者模式、备忘录模式、迭代器模式和解释器模式等。
在实际软件开发中,设计模式可以有效避免重复造轮子,提高代码的可读性和可维护性。同时,它也能够帮助开发者更加深入理解程序设计中的原则和思想。
提示:以下是本篇文章正文内容,下面案例可供参考
一、单例模式
单例模式是指一个类只能够创建一个对象实例,该实例可以被全局访问。
-
简单来说就是,借助java语法,保证某个类,只能够创建出一个实例,不能new多次。
-
有效避免了重复创建对象,节省了系统资源,同时也能够避免多个实例对象之间产生矛盾和冲突。
-
例如:JDBC中的DataSource就只需要一个。
具体的例子:打开计算机上硬盘内的文件,以不同的方式显示到屏幕上
饿汉:一次性把所有的文件内容都读取到内存中,全部显示到屏幕上(可能会导致内存占用爆满,造成电脑卡死)
懒汉:只读取一小部分,把当前的屏幕填充上,如果用户点击了翻页或滑动了滚动条,再读取剩余的一部分显示到屏幕上。(你看多少,我给多少,充分节约资源)
饿汉模式(急迫)
由于他是一个饿汉,非常急迫的想要得到食物,不管好不好吃,能不能吃,先到胃里再说,(即不管该类能不能用到,我先创建了再说,不用就一直放着)就对应了类加载的同时, 即创建实例。
代码示例
//饿汉模式
//把这个类设置为单例
class Singleton {
//被static修饰,该属性是类的属性(类对象)
//JVM中,每个类的类对象只能有唯一一份,因此,类对象里的这个成员,就是唯一的一份
private static Singleton instance = new Singleton();//唯一实例的本体
public static Singleton getInstance() {//获取到实例的方法
return instance;
}
//将构造方法设置为private,禁止外部new实例,保证唯一
private Singleton(){}
}
public class ThreadDemo {
public static void main(String[] args) {
//此时s1和s2是同一个对象
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
//new不成功,Singleton() 在 Singleton 中是 private 在访问控制
//Singleton s3 = new Singleton();
System.out.println(s1 == s2);//true,证明是同一个实例
}
}
特点
-
单线程和多线程中天生安全,只有使用对象的操作,没有创建对象的操作。
-
由于一次性加载出所有的类,可能会让初始化的效率低一些。
懒汉模式(从容)
线程不安全的版本
class Singleton {
private static Singleton instance = null;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
//一个new操作会被分为三步,任意一步都有可能被切换线程,导致出错(new出多个Singleton导致出错)
//1. 在内存中为对象分配空间;
//2. 对象的属性被初始化为默认值,如int类型的默认值为0,boolean类型的默认值为false等;
//3. 执行对象的构造函数,进行初始化操作。
}
return instance;
}
}
解决方法:
线程安全的版本
class SingletonLazy {
volatile private static SingletonLazy instance = null;//volatile保证new的过程,不会指令重排序
public static SingletonLazy getInstance() {
if (instance == null) {//减少加锁的次数,不为空不必再加锁
synchronized (SingletonLazy.class) {//保证多线程下,不会创建多个对象
if (instance == null) {//判断两次,保证多线程只有一个对象
instance = new SingletonLazy();
}
}
}
return instance;
}
private SingletonLazy() {};
}
public class ThreadDemo {
public static void main(String[] args) {
SingletonLazy s1 = SingletonLazy.getInstance();
SingletonLazy s2 = SingletonLazy.getInstance();
System.out.println(s1 == s2);
}
}
特点:
-
加锁,把if和new变成原子操作
-
双重if,如果实例已经被创建了,在第一个if中就会结束,不会尝试加锁,减少了不必要的加锁操作,减少了开销
-
使用volatile禁止指令重排序,保证后续的线程拿到的是完整对象