一、设计模式概念
1、设计模式分类(23种)
分类 | 成员 |
创建模式(5种) 提供创建对象的机制,提升已有代码的灵活性和可复用性; | 常用: 1、单例; 2、工厂:(工厂方法、抽象工厂); 3、建造者; |
不常用: 1、原型模式; | |
结构模式(7种) 如何将对象和类组装成较大的结构,并同时保持结构的灵活和高效; | 常用: 1、代理; 2、桥接; 3、装饰; 4、适配器; |
不常用: 1、外观; 2、组合; 3、享元; | |
行为模式(11种) 负责对象间的高效沟通和职责传递委派; | 常用: 1、观察者; 2、模板方法; 3、策略; 4、责任链; 5、迭代器; 6、状态; |
不常用: 1、访问者; 2、备忘录; 3、命令; 4、解释器; 5、中介者; |
2、六大设计原则(SOLID)
名称 | 定义 |
单一职责原则 Single Responsibitiyty Principle | 1、一个类(一个模块)只管一件事; 2、粒度小,功能单一; |
开闭原则 Open Close Principle | 1、对扩展开放,对修改封闭(是所有设计模式的最核心目标) 优点: 2、新老逻辑解耦,添加需求不会影响旧的逻辑; 3、改动成本低,不需要改原有逻辑; 4、提高代码的可扩展性和稳定性; |
里氏替换原则 Liskov Substitution Principle | 1、出现在多态中:接口中的方法可以被多个类实现,使用不同的实现类调用这个方法; 2、示例:interface = new Class(); 3、实际执行的是Class里面的方法; |
接口分离原则 Interface Segregation Principle | 1、应该创建职责少的interface; |
依赖倒置原则 Dependence Inversion Principle | 1、高层模块不应该直接依赖低层模块,它们都应该直接依赖抽象; 2、高层依赖interface,低层实现interface; |
迪米特法则 Least Knowledge Principle | 1、类知道的越少越好; 2、多使用中间人; |
二、创建型设计模式
创建型模式说明:创建对象的机制,提升已有代码的灵活性和复用性;
一、单例
一个类在运行的时候,只有一个实例。
使用方法:
保证一个类只有一个实例。
为这个实例提供一个全局访问点。
1、饿汉单例
package creationPattern.Singleton;
/**
* 单例模式-饿汉式
* 特点:
* 1、在类加载的时候创建【静态的私有的】对象,保证创建过程是线程安全的;
* 2、不支持延时加载,获取对象的速度快;
* 3、但如果对象比较大,而且一直没使用,就会浪费内存;
*/
public class Singleton_01 {
// 1.私有构造方法
private Singleton_01() {
}
// 2.创建私有的静态的全局对象
private static Singleton_01 instance = new Singleton_01();
// 3.给外部提供全局访问点
public static Singleton_01 getInstance() {
return instance;
}
}
2、懒汉单例 - 线程不安全
package creationPattern.Singleton;
/**
* 单例模式-懒汉式
* 1、支持延时加载,调用get方法时才会创建对象;
* 2、线程不安全
*/
public class Singleton_02 {
// 1.私有构造方法
private Singleton_02() {
}
// 2.创建私有的静态的全局对象
private static Singleton_02 instance;
// 3.给外部提供全局访问点
public static Singleton_02 getInstance() {
if (null == instance)
instance = new Singleton_02();
return instance;
}
}
3、懒汉单例 - 线程安全
package creationPattern.Singleton;
/**
* 单例模式-懒汉式
* 1、支持延时加载,调用get方法时才会创建对象;
* 2、线程安全,但是因为加了锁,导致并发度降低;
*/
public class Singleton_03 {
// 1.私有构造方法
private Singleton_03() {
}
// 2.创建私有的静态的全局对象
private static Singleton_03 instance;
// 3.给外部提供全局访问点
// 添加同步锁
public static synchronized Singleton_03 getInstance() {
if (null == instance)
instance = new Singleton_03();
return instance;
}
}
4、懒汉单例 - 双重校验:代码相对复杂
package creationPattern.Singleton;
/**
* 双重校验
* 1、get方法里面判断两次是否为null;
* 2、外层判断不空,就直接返回;
* 3、外层判断空,就抢资源,抢到资源后还需要防止前面进去的线程已经创建了;
*/
public class Singleton_04 {
// 1.私有构造方法
private Singleton_04() {
}
// 2.创建私有的静态的全局对象
// volatile 这个关键字可以保证变量的可见性,屏蔽指令重排序
private volatile static Singleton_04 instance;
// 3.给外部提供全局访问点
public static Singleton_04 getInstance() {
if (null == instance)
synchronized (Singleton_04.class){
// 抢到锁之后,第二次判断
// 进入同步代码块的线程需要防止之前进来的线程创建对象,所以需要再判断一次;
if (null == instance)
instance = new Singleton_04();
}
return instance;
}
}
5、懒汉单例 - 静态内部类:代码简单
package creationPattern.Singleton;
/**
* 静态内部类
* 1、利用静态内部类的特性:外部类使用到了内部类的属性或者方法时,才会加载内部类;
* 2、实现延时加载、线程安全、代码简单
* 3、静态内部类里面实际上也是一个饿汉加载,只是类不被加载,它没办法创建实例;
*/
public class Singleton_05 {
// 1.私有构造方法
private Singleton_05() {
if (null != SingletonHandler.instance) {
throw new RuntimeException("非法访问构造方法");
}
}
// 2.创建静态内部类
private static class SingletonHandler {
// 3.创建私有的静态的全局对象
private static Singleton_05 instance = new Singleton_05();
}
// 4.提供外部方法
public static Singleton_05 getInstance() {
return SingletonHandler.instance;
}
}
6、反射对单例的破坏
package creationPattern.Singleton;
import java.lang.reflect.Constructor;
/**
* 反射对单例的破坏
*/
public class Test_Reflect {
public static void main(String[] args) {
Class<Singleton_05> clazz = Singleton_05.class;
try {
// 获取私有构造方法
Constructor<Singleton_05> constructor = clazz.getDeclaredConstructor();
constructor.setAccessible(true);
Singleton_05 singleton05 = constructor.newInstance();
System.out.println(singleton05);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
-- 加个判断解决
9、序列化对单例有破坏
10、系列化对单例有破坏
11、使用枚举实现的单例模式具有懒加载、线程安全、不被反射和序列化破坏的特点;