设计模式

这里写目录标题

单例设计模式

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

懒汉模式 注释写的很清楚

在这里插入图片描述

代码实现

package com.luyi.designpattern;

/**
 * 懒汉模式
 * @author 卢意
 * @create 2020-12-28 20:06
 */
public class LazySingletonTest {
   
	public static void main(String[] args) {
   
		// 最基础的单例模式
//		LazySingleton instance = LazySingleton.getInstance();
//		LazySingleton instance1 = LazySingleton.getInstance();
//		System.out.println(instance == instance1); // TRUE

		// 多线程环境下的问题
		new Thread(()-> {
   
			LazySingleton instance = LazySingleton.getInstance();
			System.out.println(instance);
		}).start();

		new Thread(()-> {
   
			LazySingleton instance = LazySingleton.getInstance();
			System.out.println(instance);
		}).start();
		// 多线程不是单例
		// com.luyi.designpattern.LazySingleton@5e5035fb
		//com.luyi.designpattern.LazySingleton@6a3289ca

		// 构造函数加入 synchronized 字段 加锁 但是会有性能损耗
		//com.luyi.designpattern.LazySingleton@5e5035fb
		//com.luyi.designpattern.LazySingleton@5e5035fb

		// 可以在 INSTANCE == null 时再加锁 减少不必要的锁
	}
}

class LazySingleton {
   
	// private  static LazySingleton INSTANCE;
	private volatile static LazySingleton INSTANCE; //加入volatile 字段 保证不会重排序 
	private LazySingleton() {
   

	}

	public static LazySingleton getInstance() {
   
		if (INSTANCE == null) {
   
			synchronized (LazySingleton.class) {
   
				if (INSTANCE == null) {
    // 多判断一次 防止多线程情况 同时进入这个锁
					INSTANCE = new LazySingleton();
					// 声明对象时 在字节码层
					// JIT(即时遍历) CPU 会指令顺序重排  单线程模式下 第2步和第三步可以颠倒 多线程情况下 如果先进行引用赋值 就会导致
					// 未初始化就被赋值的 会导致空指针针  加入volatile 字段 保证不会重排序
					// 1 分配空间
					// 2 进行初始化
					// 3 引用赋值
					//
				}
			}
//			try {
   
//				Thread.sleep(3000);
//			} catch (InterruptedException e) {
   
//				e.printStackTrace();
//			}
			//
		}
		return INSTANCE;
	}
}

饿汉模式

在这里插入图片描述

代码实现 利用jvm的类加载机制 保证实例的唯一性(比懒汉模式简单的多)

package com.luyi.designpattern;

/**
 * 饿汉模式
 * @author 卢意
 * @create 2020-12-28 21:01
 */
public class HungrySingletonTest {
   
	public static void main(String[] args) {
   

		HungrySingleton instance = HungrySingleton.getInstance(); // 加载 HungrySingleton 的类加载机制 
		HungrySingleton instance2 = HungrySingleton.getInstance();
		System.out.println(instance == instance2); //true
	}
}

// 初始阶段就完成了类的初始实例化 本质上借助于jvm的类加载机制 保证实例的唯一性
// 类加载过程:
// 加载二进制数据到内存中 生成对应的class数据结构
// 连接 验证 准备(给类的静态成员变量符初值) 解析
// 初始化 : 给类的静态变量赋初值
class HungrySingleton {
   
	private static HungrySingleton INSTANCE = new HungrySingleton();
	private HungrySingleton() {
   

	}
	public static HungrySingleton getInstance() {
   
		return INSTANCE;
	}
}

静态内部类

在这里插入图片描述

代码实现 也是通过jvm的类加载机制保证了线程的安全 但是是在使用的时候调用 不是创建类的时候调用

package com.luyi.designpattern;

import java.util.Stack;

/**静态内部类实现单例模式
 * @author 卢意
 * @create 2020-12-28 21:11
 */
public class InnerClassSingletonTest {
   
	public static void main(String[] args) {
   
		InnerClassSingleton instance = InnerClassSingleton.getInstance();
		InnerClassSingleton instance2 = InnerClassSingleton.getInstance();
		System.out.println(instance == instance2); // true

		new Thread(()-> {
   
			InnerClassSingleton instance3 = InnerClassSingleton.getInstance();
			System.out.println(instance3);
		}).start();

		new Thread(()-> {
   
			InnerClassSingleton instance4 = InnerClassSingleton.getInstance();
			System.out.println(instance4);
		}).start();
		// 是线程安全的
		//com.luyi.designpattern.InnerClassSingleton@74f84cf
		//com.luyi.designpattern.InnerClassSingleton@74f84cf
	}
}
// 也是依赖jvm的类加载机制来保证线程安全
class InnerClassSingleton {
   
	private static  class InnerClassHolder {
    // 在调用getInstance() 时再会进行加载 (懒加载)
		private static InnerClassSingleton INSTANCE = new InnerClassSingleton();
	}
	private InnerClassSingleton() {
   

	}
	public static InnerClassSingleton getInstance() {
   
		return InnerClassHolder.INSTANCE;
	}
}

反射攻击

上面的模式在反射的情况下 还是会有风险
在这里插入图片描述

防止反射攻击

在初始化类的时候判断是否已经存在实例

private InnerClassSingleton() {
   
		if (InnerClassHolder.INSTANCE != null) {
   
			throw  new RuntimeException(" 单例不允许多个实例 ");
		}
	}

枚举类型的单例实现 防止反射攻击 也是通过jvm的类加载机制 保证了代码的线程安全

在这里插入图片描述

package com.luyi.designpattern;

/**
 * 枚举实现单例模式 防止反射攻击
 * @author 卢意
 * @create 2020-12-28 21:36
 */
public enum   EnumSingleton {
   
	INSTANCE;

	public void print() {
   
		System.out.println(this.hashCode());
	}
}
// 看似代码量很少 但是jvm的操作很多  性能消耗比较大

class EnumTest {
   
	public static void main(String[] args) {
   
		EnumSingleton instance = EnumSingleton.INSTANCE;
		EnumSingleton instance2 = EnumSingleton.INSTANCE;
		System.out.println(instance == instance2); // true
	}
}

序列化对单例模式的攻击

在这里插入图片描述

防止序列化攻击

注意要加版本号 不然会报错
在这里插入图片描述

运行时异常就是单例模式(饿汉模式)

spring的bean代理工厂有针对单例模式的变量

在这里插入图片描述

工厂方法模式

引入设计模式的前提就是 需要找到代码内的稳定的部分 和变化的部分 变化的过程中找的稳定的部分 (个人理解就是面向接口(抽象类)编程 比如’变化的过程中找的稳定的部分’ 就是重写接口(继承的抽象类)的方法 或者说是实现接口(继承抽象类)的类所公共的部分 代码复用…)

在这里插入图片描述

简单工厂 和 工厂方法模式 的区别

简单工厂并不是一种设计模式 而是一种编码方式

简单工厂的编码方式(编程习惯)

package com.luyi.designpattern;

/** 简单工厂模式
 * @author 卢意
 * @create 2020-12-29 20:28
 */
public class FactoryMethod {
   

	public static void main(String[] args) {
   
		Application application = new Application();
		Product product = application.getObject("1");
		product.method1();
	}
}

class SimpleFactory {
   
	public static Product createProduct(String type) {
   
		 if ("0".equals(type)) {
   
		 	return new ProductA();
		 } else if ("1".equals(type)) {
   
		 	return new Product1();
		 }
		 return null;
	}
}
interface Product {
   
	public void method1();
}
// 未使用设计模式的方案
//class ProductA {
   
//	public void method1() {
   
//		System.out.println("ProductA.method executed");
//	}
//
//}

class ProductA implements Product {
   

	@Override
	public void method1() {
   
		System.out.println("ProductA.method executed");
	}
}

class Product1 implements Product {
   

	@Override
	public void method1() {
   
		System.out.println("Product1.method executed");
	}
}

class Application {
   
//	private  ProductA createProduct() {
   
//		// ... init
//		return new ProductA();
//	}

	private Product createProduct(String type) {
   
		// ... init

		return SimpleFactory.createProduct("1"); // 多态
	}

	Product getObject(String type) {
   
		Product product = createProduct(type); // 多态

		//..
		return  product;
	}
}

工厂方法模式

工厂方法模式是一种设计模式 是将 产品具体实例化的过程推迟给其子类实现
符和开闭原则(对拓展开放 对修改关闭)
符和单一职责原则

package com.luyi.designpattern;

/**
 * @author 卢意
 * @create 2020-12-29 20:28
 */
public class FactoryMethod {
   

	public static void main(String[] args) {
   
		Application application = new ConcreateProductA();
		Product product = application.getObject();
		product.method1(); // res = ProductA.method executed
	}
}

interface Product {
   
	public void method1();
}

class ProductA implements Product {
   
	@Override
	public void method1() {
   
		System.out.println("ProductA.method executed");
	}
}

class Product1 implements Product {
   
	@Override
	public void method1() {
   
		System.out.println("Product1.method executed");
	}
}

abstract class  Application {
   

	// 创建对象是稳定的部分  不稳定的是具体的实现 (返回值) 说以符和设计模式的思想  将该类设置成抽象类 稳定的部分设置成抽象方法
	abstract Product createProduct();
	Product getObject() {
   
		Product product = createProduct(); // 多态
		// .. 不同的的处理
		// .. 不同的的处理
		return  product;
	}
}


class ConcreateProductA extends Application {
   

	@Override
	Product createProduct() {
   
		// .. 不同的的处理
		return new ProductA();
	}
}

class ConcreateProduct1 extends Application {
   

	@Override
	Product createProduct() {
   
		// .. 不同的的处理
		return new Product1();
	}
}

应用场景

在这里插入图片描述

抽象工厂模式

在这里插入图片描述
与工厂方法的区别是 在定义了一个 接口 整合了其他相关的接口 也可以说 抽象工厂模式是由一系列工厂方法模式组合而成的
在这里插入图片描述

package com.luyi.designpattern;

/**
 * @author 卢意
 * @create 2020-12-30 21:17
 */
public class AbstractFactory {
   
	public static void main(String[] args) {
   
		IDataBaseUtils iDataBaseUtils = new MysqlDataBaseUtils();
		IConnection connection = iDataBaseUtils.getConnection();
		connection.connect();
		ICommand command = iDataBaseUtils.getCommand();
		command.command();
	}
}

// 如果模拟的是数据的操作  变化的部分 就是 mysql 或者 oracle
//         稳定的部分  连接connection  命令sql的执行command
interface IConnection {
   
	void connect();
}

interface ICommand {
   
	void  command();
}

interface  IDataBaseUtils {
   
	IConnection getConnection();
	ICommand getCommand();
}

class MysqlConnection implements IConnection {
   

	@Override
	public void connect() {
   
		System.out.println("mysql connected");
	}
}

class MySqlC
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值