什么是设计模式?
- [ 设计模式:是一套被反复使用,多数人知晓的,经过分类的。前人代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码的可靠性、程序的重用性。]
1、 为什么要学习设计模式?
- 看懂源码、看懂源码、看懂源码,不懂源码,你的代码之路很难!
- 接盘。去了另外一家公司,接盘他人的项目,看别人的代码容易上手。
- 规范自己的代码。有了规范,大家都好办事。
2、设计模式分类
- 创建型模式:(五种)工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
- 结构型模式:(七种)适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
- 行为型模式:(十一种)策略模式、模板方法模式、观测者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
3、设计模式的六大原则
- 开发封闭原则
- 里氏代换原则
- 依赖倒转原则
- 接口隔离原则
- 迪米特法(最少知道原则)
- 单一职责原则
4、 单例模式
4.1 什么是单例
保证一个类只有一个实例,并且提供一个访问该全局的访问点
4.2 那些地方用到了单例模式
- 网站的计算器;
- 应用程序的日志应用;
- 多线程的线程池的设计一般是采用单例模式;
- windows的任务管理器
4.3 单例防止反射漏洞攻击
package 设计模式.单例模式;
public class 单例防止反射漏洞攻击 {
private static boolean flag = false;
private 单例防止反射漏洞攻击(){
if (flag == false){
flag = !flag;
}else {
throw new RuntimeException("单例模式被侵犯!");
}
}
public static void main(String[] args) {
}
}
4.4 如何选择单例模式
如果不需要延迟加载单例模式,可以使用枚举或者饿汉式,相对来说枚举性好于饿汉式。如果需要延迟加载,可以使用加载,可以使用静态内部类或者懒汉式,相对来说静态内部类好于懒汉式,最好使用饿汉式!!!
5、单例创建方式
5.1 饿汉式
饿汉式:类初始化时,就会立即加载该对象,线程天生安全,调用效率高
package 设计模式.单例模式;
public class 饿汉式 {
// 类初始化时,就会立即加载该对象,线程安全,调用效率高
private static 饿汉式 person = new 饿汉式();
private 饿汉式(){
System.out.println("私有化构造器");
}
public static 饿汉式 getInstance(){
return person;
}
public static void main(String[] args) {
饿汉式 p1 = 饿汉式.getInstance();
饿汉式 p2 = 饿汉式.getInstance();
System.out.println(p1==p2);
}
}
5.2 懒汉式
懒汉式:类初始化时,不会初始化该对象,真正需要使用的时候才会创建该对象,具备懒加载功能
package 设计模式.单例模式;
public class 懒汉式 {
// 类初始化时,就会立即加载该对象,线程安全,调用效率高
private static 懒汉式 person;
private 懒汉式(){
System.out.println("私有化构造器");
}
public synchronized static 懒汉式 getInstance(){
if(person == null){
person = new 懒汉式();
}
return person;
}
public static void main(String[] args) {
懒汉式 p1 = 懒汉式.getInstance();
懒汉式 p2 = 懒汉式.getInstance();
System.out.println(p1 == p2);//true
}
}
5.3 静态内部类
静态内部类:结合了懒汉式和饿汉式各自的优点,真正需要的对象才会加载,加载类是线程安全的。
package 设计模式.单例模式;
public class 静态内部类 {
private 静态内部类(){
System.out.println("构造器私有化");
}
public static class SingletonClassInstance{
private static final 静态内部类 person = new 静态内部类();
}
// 方法没有同步
public static 静态内部类 getInstance(){
return SingletonClassInstance.person;
}
public static void main(String[] args) {
静态内部类 p1 = 静态内部类.getInstance();
静态内部类 p2 = 静态内部类.getInstance();
System.out.println(p1 == p2);
}
}
5.4 枚举单例式
枚举单例式:
优点:实现简单、调用效率高,枚举本身就是单例,由jvm从根本上提供保障!避免通过反射和反序列化的漏洞。
缺点:没有延迟加载。
package 设计模式.单例模式;
public class 枚举单例式 {
// 定义枚举
private static enum Demo{
INSTANCE;
// 枚举元素为单例
private 枚举单例式 person;
private Demo(){
System.out.println("枚举Demo私有构造参数");
person = new 枚举单例式();
}
public 枚举单例式 getInstance(){
return person;
}
}
public static 枚举单例式 getInstance(){
return Demo.INSTANCE.getInstance();
}
public static void main(String[] args) {
枚举单例式 p1 = 枚举单例式.getInstance();
枚举单例式 p2 = 枚举单例式.getInstance();
System.out.println(p1 == p2);
}
}