前言
在我们平时的工作学习中,代码的整洁与高可用会让程序更加有效率,对项目的好处不言而喻。
设计模式的学习会让我们的编程水平得到很大的提升,同时也有助于对框架的理解,因为优秀的框架结构都用到了设计模式。
今天先瞅瞅单例模式,剩余的设计模式我也会慢慢更新,做一个系列。
设计模式(design pattern)?
设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。 是对面向对象设计中反复出现的问题的解决方案
使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。
Java设计模式贯彻的原理是:面向接口编程,而不是面向实现。其目标的原则是:降低耦合,增强灵活性。
设计模式分类:
一、创建型模式
创建型模式是用来创建对象的模式,抽象了实例化的过程,帮助一个系统独立于其关联对象的创建、组合和表示方式。
所有的创建型模式都有两个主要功能:
- 将系统所使用的具体类信息封装起来;
- 隐藏类的实例是如何被创建和组织的。外界对于这些对象只知道他们共同的接口,而不清楚其具体的实现细节。
常见的创建型模式:
- 单例模式(Singleton Pattern)
- 工厂方法模式(Factory Pattern)
- 抽象工厂模式(Abstract Factory Pattern)
- 建造者模式(Builder Pattern)
- 原型模式(Prototype pattern)
二 、结构型模式
结构型模式讨论的是类和对象的结构,它采用继承机制来组合接口或实现(类结构型模式),或者通过组合一些对象实现新的功能(对象结构型模式)。
常见结构型模式:
- 代理模式(Proxy)
- 装饰模式(Decorator)
- 适配器模式(Adapter)
- 组合模式(Composite)
- 桥梁模式(Bridge)
- 外观模式(Facade)
- 享元模式(Flyweight)
三、行为型模式
行为型模式关注的是对象的行为,用来解决对象之间的联系问题。
常见行为型模式:
- 模板方法模式(Template Method)
- 命令模式(Commend)
- 责任链模式(Chain of Responsibility)
- 策略模式(Strategy)
- 迭代器模式(Iterator)
- 中介者模式(Mediator)
- 观察者模式(Observer)
- 备忘录模式(Memento)
- 访问者模式(Visitor)
- 状态模式(State)
- 解释器模式(Interpreter)
Singleton Pattern(单例模式)?
定义:Ensure a class has only one instance, and provide a global Point of access to it.
确保一个类只有一个实例存在。
最好学习方法就是分析代码:
饿汉式
/**
* 饿汉式(类加载时,就进行对象实例化)
* 类加载到内存后,就实例化一个单例,JVM保证线程安全
* 类只加载一次,实例化一次 Class.forName()
* 缺点:类完成加载,就完成实例化
*/
public class Manager01 {
//private确保构造方法无法被外界实例化
private Manager01(){
}
//静态常量(或变量)
private static final Manager01 INSTANCE = new Manager01();
//通过该方法获得实例
public static Manager01 getInstance(){
return INSTANCE;
}
//其余业务方法
public void useOthers(){
}
public static void main(String[] args) {
Manager01 instance1 = Manager01.getInstance();
Manager01 instance2 = Manager01.getInstance();
//输出结果为True,同一个对象
System.out.println(instance1==instance2);
}
}
懒汉式
/**
* 懒汉式(第一次引用类时,才进行对象实例化)
* Lazy Loading
* 按需初始化,但要保证多线程并发安全
*/
public class Manager02 {
private Manager02(){}
private static Manager02 INSTANCE;
public static Manager02 getInstance(){
//public static synchronized Manager02 getInstance()
//加锁亦可在方法上,保证同步,多线程容易发生创建多个实例
synchronized (Manager02.class){
//判断是否已实例化
if (INSTANCE==null){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
INSTANCE = new Manager02();
}
return INSTANCE;
}
}
//业务方法等
public void useOthers(){}
public static void main(String[] args) {
//创建100个线程,结果只有一个实例被创建
for (int i = 0; i < 100; i++) {
//lambda表达式
new Thread(()->{
System.out.println(Manager02.getInstance().hashCode());
}).start();
}
}
}
双重判断
懒汉式模式会加锁,导致效率降低,双重模式是对懒汉的优化
/**
* 双重判断
*/
public class Manager03 {
private Manager03(){}
private static Manager03 instance;
public static Manager03 getInstance(){
//判断第一次,若实例已存在,直接跳转返回instance。无需等待锁的释放
if (instance==null){
synchronized (Manager03.class){
//二次判断,若此时已存在实例,就跳过if块
if (instance==null){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
instance = new Manager03();
return instance;
}
}
}
return instance;
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(()->{
System.out.println(Manager03.getInstance().hashCode());
}).start();
}
}
}
静态内部类
/**
* 静态内部类
* 加载外部类时不会加载内部类,懒加载
*/
public class Manager04 {
private Manager04(){}
private static class managerHolder {
private final static Manager04 INSTANCE = new Manager04();
}
public static Manager04 getInstance(){
return managerHolder.INSTANCE;
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(()->{
System.out.println(Manager04.getInstance().hashCode());
}).start();
}
}
}
枚举式
/**
* 枚举单例
* 大佬写的,不仅解决线程同步,还可以反序列化
* 完美
*/
public enum Manager05 {
INSTANCE;
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(()->{
System.out.println(Manager05.INSTANCE.hashCode());
}).start();
}
}
}
最常用最简单的就是饿汉式,懒汉式了。
上面示例为看视频总结手敲,很精妙