设计模式

本文详细介绍了多种设计模式,包括单例模式的懒汉、饿汉、静态内部类及枚举实现,防止反射和序列化攻击的策略,工厂方法模式、抽象工厂模式、建造者模式、原型模式、享元模式、门面模式、适配器模式、装饰者模式、策略模式、模板模式、观察者模式、责任链模式,并讨论了面向对象设计原则SOLID。
摘要由CSDN通过智能技术生成

这里写目录标题

单例设计模式

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

懒汉模式 注释写的很清楚

在这里插入图片描述

代码实现

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 MySqlCommand implements ICommand {

	@Override
	public void command() {
		System.out.println("mysql Command");
	}
}

class MysqlDataBaseUtils implements  IDataBaseUtils {

	@Override
	public IConnection getConnection() {
		return new MysqlConnection();
	}

	@Override
	public ICommand getCommand() {
		return new MySqlCommand();
	}
}


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

建造者模式

主要是和不可变对象进行配合使用
在这里插入图片描述

代码实现 适用于创建复杂的对象 主要是用于确定构建顺序和构建时的特殊操作

package com.luyi.designpattern.buider;

/**
 * 建造者模式
 * @author 卢意
 * @create 2021-01-03 10:17
 */
public class BuilderTest {
	public static void main(String[] args) {
		// 传统的构造模式
		Product product = new Product();
		product.setPart1("XX");
		//....  需要set很多 比较复杂和混乱 可能需要系统的构造顺序

		// 可以用建造者模式进行优化
		DefaultConcreateProductBuilder builder = new DefaultConcreateProductBuilder();
		// 建造者的指导
		Director director = new Director(builder);
		Product product1 = director.makeProduct("cName", "pName", "p1", "p2", "p3", "p4");
		System.out.println(product1);
		// Result : Product{part1='pName', part2='cName', part3='p1', part4='p3', productName='p2', companyName='p4'}
	}
}

interface ProductBuilder {
	void builderProductName(String productName);
	void builderCompanyName(String companyName);
	void builderPart1(String part1);
	void builderPart2(String part2);
	void builderPart3(String part3);
	void builderPart4(String part4);

	Product builder();
}

// 默认构造方式
class DefaultConcreateProductBuilder implements ProductBuilder {

	private String productName;
	private String companyName;
	private String part1;
	private String part2;
	private String part3;
	private String part4;

	@Override
	public void builderProductName(String productName) {
		this.productName = productName;
	}

	@Override
	public void builderCompanyName(String companyName) {
		this.companyName = companyName;
	}

	@Override
	public void builderPart1(String part1) {
		this.part1 = part1;
	}

	@Override
	public void builderPart2(String part2) {
		this.part2 = part2;
	}

	@Override
	public void builderPart3(String part3) {
		this.part3 = part3;
	}

	@Override
	public void builderPart4(String part4) {
		this.part4 = part4;
	}

	@Override
	public Product builder() {
		return new Product(this.productName, this.companyName, this.part1, this.part2, this.part3, this.part4);
	}
}

class SpecialConcreateProductBuilder implements ProductBuilder {
	private String productName;
	private String companyName;
	private String part1;
	private String part2;
	private String part3;
	private String part4;

	@Override
	public void builderProductName(String productName) {
		this.productName = productName;
	}

	@Override
	public void builderCompanyName(String companyName) {
		this.companyName = companyName;
	}

	@Override
	public void builderPart1(String part1) {
		this.part1 = part1;
	}

	@Override
	public void builderPart2(String part2) {
		this.part2 = part2;
	}

	@Override
	public void builderPart3(String part3) {
		this.part3 = part3;
	}

	@Override
	public void builderPart4(String part4) {
		this.part4 = part4;
	}

	@Override
	public Product builder() {
		return new Product(this.productName, this.companyName, this.part1, this.part2, this.part3, this.part4);
	}
}

class Director {
	private ProductBuilder builder;

	Director ( ProductBuilder builder) {
		this.builder = builder;
	}

	public Product makeProduct(String companyName, String productName, String part1, String part3,
							   String part2, String part4) {
		// 控制建造的顺序
		builder.builderCompanyName(companyName);
		builder.builderProductName(productName);
		builder.builderPart1(part1);
		builder.builderPart3(part3);
		builder.builderPart2(part2);
		builder.builderPart4(part4);
		return builder.builder();
	}
}

class Product {
	private String productName;
	private String companyName;
	private String part1;
	private String part2;
	private String part3;
	private String part4;

	Product() {

	}
	public Product(String part1, String part2, String part3, String part4, String productName, String companyName) {
		this.part1 = part1;
		this.part2 = part2;
		this.part3 = part3;
		this.part4 = part4;
		this.productName = productName;
		this.companyName = companyName;
	}

	public String getPart1() {
		return part1;
	}

	public void setPart1(String part1) {
		this.part1 = part1;
	}

	public String getPart2() {
		return part2;
	}

	public void setPart2(String part2) {
		this.part2 = part2;
	}

	public String getPart3() {
		return part3;
	}

	public void setPart3(String part3) {
		this.part3 = part3;
	}

	public String getPart4() {
		return part4;
	}

	public void setPart4(String part4) {
		this.part4 = part4;
	}

	public String getProductName() {
		return productName;
	}

	public void setProductName(String productName) {
		this.productName = productName;
	}

	public String getCompanyName() {
		return companyName;
	}

	public void setCompanyName(String companyName) {
		this.companyName = companyName;
	}

	@Override
	public String toString() {
		return "Product{" +
				"part1='" + part1 + '\'' +
				", part2='" + part2 + '\'' +
				", part3='" + part3 + '\'' +
				", part4='" + part4 + '\'' +
				", productName='" + productName + '\'' +
				", companyName='" + companyName + '\'' +
				'}';
	}
}

代码实现 一个变种 是和不可变对象进行配合使用

package com.luyi.designpattern.buider.v2;

/**
 * @author 卢意
 * @create 2021-01-03 10:51
 */
public class BuilderTest2 {
	public static void main(String[] args) {
		Product product = new Product.Builder().productName("xxx").companyName("xxx").
				part1("xx").part2("xx").part3("xx").part4("xx")
				.build();
		System.out.println(product);
	}
}


class Product {
	// 比如一些配置项信息
	private final String productName;
	private final String companyName;
	private final String part1;
	private final String part2;
	private final String part3;
	private final String part4;


	public Product(String productName, String companyName, String part1, String part2, String part3, String part4) {
		this.part1 = part1;
		this.part2 = part2;
		this.part3 = part3;
		this.part4 = part4;
		this.productName = productName;
		this.companyName = companyName;
	}

	// 静态内部类 创造者
	static class Builder {
		private String productName;
		private String companyName;
		private String part1;
		private String part2;
		private String part3;
		private String part4;

		public Builder productName(String productName) {
			this.productName = productName;
			return this;
		}

		public Builder companyName(String companyName) {
			this.companyName = companyName;
			return this;
		}

		public Builder part1(String part1) {
			this.part1 = part1;
			return this;
		}

		public Builder part2(String part2) {
			this.part2 = part2;
			return this;
		}

		public Builder part3(String part3) {
			this.part3 = part3;
			return this;
		}

		public Builder part4(String part4) {
			this.part4 = part4;
			return this;
		}

		Product build() {
			// ..
			return new Product(this.productName, this.companyName, this.part1, this.part2, this.part3, this.part4);
		}
	}

	@Override
	public String toString() {
		return "Product{" +
				"part1='" + part1 + '\'' +
				", part2='" + part2 + '\'' +
				", part3='" + part3 + '\'' +
				", part4='" + part4 + '\'' +
				", productName='" + productName + '\'' +
				", companyName='" + companyName + '\'' +
				'}';
	}
}

应用场景

在这里插入图片描述

原型模式

在这里插入图片描述

浅拷贝和深拷贝

(1)、定义
被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。即对象的浅拷贝会对“主”对象进行拷贝,但不会复制主对象里面的对象。”里面的对象“会在原来的对象和它的副本之间共享。

简而言之,浅拷贝仅仅复制所考虑的对象,而不复制它所引用的对象。

浅拷贝 如下图 如果拷贝对象和被考别对象 有一点点关系(指向同一个地址) 就是浅拷贝
在这里插入图片描述

在这里插入图片描述

(1)、定义
深拷贝是一个整个独立的对象拷贝,深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。

简而言之,深拷贝把要复制的对象所引用的对象都复制了一遍。

深拷贝 如下图 如果拷贝对象和被考别对象 有一点点关系(指向同一个地址)都没有 就是深拷贝
在这里插入图片描述
在这里插入图片描述

代码实现 深拷贝和利用序列化机制进行深拷贝 注释写得很多知识点 注意阅读

package com.luyi.designpattern.prototype;

import java.io.*;

/**
 * // 原型模式
 * @author 卢意
 * @create 2021-01-03 11:18
 */
public class PrototypeTest {
	public static void main(String[] args) throws CloneNotSupportedException {
		BaseInfo baseInfo = new BaseInfo("xxx");
		// 传统获取Product对象的方式
		Product product = new Product("part1", "part2", "part3", "part4", baseInfo);
		// 如果需要100个product对象  就需要new 100次 ....

		// 可以用原型模式  通过实现java的克隆机制对Product对象进行拷贝
		Product clone = product.clone();
		System.out.println("original: "+ product);
		System.out.println("clone: "+ clone);
		// 优化前Result:
		//  original:  hashCode= 356573597 Product{part1='part1', part2='part2', part3='part3', part4='part4', baseInfo=BaseInfo{hashCode='1735600054'companyName='xxx'}}
		//  clone:  hashCode= 21685669 Product{part1='part1', part2='part2', part3='part3', part4='part4', baseInfo=BaseInfo{hashCode='1735600054'companyName='xxx'}}
		// 会发现上面的baseInfo是同一个对象
		// 这样的克隆是复制了原对象的地址 地址拷贝进来 当克隆后对源对象的某个属性进行该改变,克隆的对象的该属性也会进行改变, 克隆对象和源对象还是存在依赖性
		// 需要对可变对象进行深拷贝

		// 优化后 Result:
		// original:  hashCode= 356573597 Product{part1='part1', part2='part2', part3='part3', part4='part4', baseInfo=BaseInfo{hashCode='1735600054'companyName='xxx'}}
		//  clone:  hashCode= 21685669 Product{part1='part1', part2='part2', part3='part3', part4='part4', baseInfo=BaseInfo{hashCode='2133927002'companyName='xxx'}}
	}
}

// 如果被克隆对象包含了 BaseInfo这个方法 BaseInfo也需要实现Cloneable方法 被克隆对象通过先对baseInfo进行克隆
// 克隆对象的baseInfo属性是被克隆对象的BaseInfo属性的克隆对象  保证了克隆对象的BaseInfo属性和被克隆对象的BaseInfo对象 不是同一个对象(应用地址)
// 有点绕 多看几遍
class BaseInfo implements Cloneable, Serializable{
	private String companyName;

	public BaseInfo(String companyName) {
		this.companyName = companyName;
	}

	public String getCompanyName() {
		return companyName;
	}

	public void setCompanyName(String companyName) {
		this.companyName = companyName;
	}

	@Override
	protected BaseInfo clone() throws CloneNotSupportedException {
		return (BaseInfo) super.clone();
	}

	@Override
	public String toString() {
		return "BaseInfo{" +
				"hashCode='" + hashCode() + '\'' +
				"companyName='" + companyName + '\'' +
				'}';
	}
}

// 实现Cloneable 接口 让Product类具有克隆的能力   Serializable是V2的利用序列化深拷贝使用的
class Product implements Cloneable, Serializable{
	static final long serialVersionID = 42L;
	private String part1;
	private String part2;
	private String part3;
	private String part4;
	private BaseInfo baseInfo;


	public Product(String part1, String part2, String part3, String part4, BaseInfo baseInfo) {
		this.part1 = part1;
		this.part2 = part2;
		this.part3 = part3;
		this.part4 = part4;
		// 八大基本数据类型和包装类 及 String类 都是 不可变类型 对上述的属性进行克隆是没问题的
		this.baseInfo = baseInfo; // 但是这种可变类型的属性拷贝就会有一定风险
	}

	public String getPart1() {
		return part1;
	}

	public void setPart1(String part1) {
		this.part1 = part1;
	}

	public String getPart2() {
		return part2;
	}

	public void setPart2(String part2) {
		this.part2 = part2;
	}

	public String getPart3() {
		return part3;
	}

	public void setPart3(String part3) {
		this.part3 = part3;
	}

	public String getPart4() {
		return part4;
	}

	public void setPart4(String part4) {
		this.part4 = part4;
	}

	public BaseInfo getBaseInfo() {
		return baseInfo;
	}

	public void setBaseInfo(BaseInfo baseInfo) {
		this.baseInfo = baseInfo;
	}

	// 实现克隆的接口

	@Override
	protected Product clone() throws CloneNotSupportedException {
		// 但是这样的克隆是复制了原对象的地址 地址拷贝进来 当克隆后对源对象的某个属性进行该改变,克隆的对象的该属性也会进行改变, 克隆对象和源对象还是存在依赖性
		// return (Product) super.clone();

//		// 优化 v1 对可变变量在进行一次拷贝
//		Product product = (Product) super.clone();
//		product.setBaseInfo(product.getBaseInfo().clone());
//		return product;
		// 优化 v2 利用java的序列化机制 实现深拷贝 比交消耗性能 速度较慢 不推荐
		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

		try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream)) {
			objectOutputStream.writeObject(this);
		} catch (IOException e) {
			e.printStackTrace();
		}
		ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());

		try(ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream)) {
			return (Product)objectInputStream.readObject();
		} catch (IOException | ClassNotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public String toString() {
		return " hashCode= " + super.hashCode() + " Product{" +
				"part1='" + part1 + '\'' +
				", part2='" + part2 + '\'' +
				", part3='" + part3 + '\'' +
				", part4='" + part4 + '\'' +
				", baseInfo=" + baseInfo +
				'}';
	}
}

应用场景

在这里插入图片描述

享元模式

因为要共享 要保证数据的线程安全(数据一致性和不可变性)

在这里插入图片描述

代码实现

package com.luyi.designpattern.flyweight;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/** 享元模式
 * @author 卢意
 * @create 2021-01-03 14:31
 */
public class FlyWeightTest {
	public static void main(String[] args) {
		TreeNode treeNode = new TreeNode(0, 4, TreeFactory.getTree("xxx", "xxxxxx"));
		TreeNode treeNode1 = new TreeNode(1, 2, TreeFactory.getTree("xxx", "xxxxxx"));
		// result:   (相同的名字的树只创建了一次)
		// 创建树 name = xxx data = xxxxxx
	}
}

// 生成Tree对象的工厂
class TreeFactory {
	private static Map<String, Tree> map = new ConcurrentHashMap<>();

	public static Tree getTree(String name, String data) {
		if (map.containsKey(name)) {
			return map.get(name);
		}
		Tree tree = new Tree(name, data);
		map.put(name, tree);
		return tree;
	}
}

// 树的坐标信息类
class TreeNode {
	private int x;
	private int y;
	private Tree tree;

	public TreeNode(int x, int y, Tree tree) {
		this.x = x;
		this.y = y;
		this.tree = tree;
	}

	public int getX() {
		return x;
	}

	public void setX(int x) {
		this.x = x;
	}

	public int getY() {
		return y;
	}

	public void setY(int y) {
		this.y = y;
	}

	public Tree getTree() {
		return tree;
	}

	public void setTree(Tree tree) {
		this.tree = tree;
	}
}

// 树对象 不提供set方法 不可变对象 保证多线程环境下的线程安全
class Tree {
	private final String name;
	private final String data;

	public Tree(String name, String data) {
		System.out.println("创建树 name = " + name + " data = " + data);
		this.name = name;
		this.data = data;
	}

	public String getName() {
		return name;
	}


	public String getData() {
		return data;
	}
}

门面模式

比如controller相当于 Facade service的实现类相当与子系统 客户端调用相应的controller就可以了
在这里插入图片描述
在这里插入图片描述

代码实现

package com.luyi.designpattern.facade;

/**
 * 门面模式  比如controller相当于 Facade  service的实现类相当与子系统  客户端调用相应的controller就可以了
 * @author 卢意
 * @create 2021-01-03 14:58
 */
public class FacadeTest {
	public static void main(String[] args) {
		
	}
}

// 客户端们
class Client1 {
	Facade facade = new Facade();
	public void doSomething1() {
		facade.doSomething1();
	}
}

class Client2 {
	Facade facade = new Facade();

	public void doSomething2() {
		facade.doSomething2();
	}
}

// 门面 客户端去调用它 间接调用子系统 就不需要客户端先去考虑调用哪个子系统的哪些方式
class Facade {
	SubSystem1 subSystem1 = new SubSystem1();
	SubSystem2 subSystem2 = new SubSystem2();
	SubSystem3 subSystem3 = new SubSystem3();

	public void doSomething2() {
		this.subSystem1.method1();
		this.subSystem2.method2();
		this.subSystem3.method3();
	}

	public void doSomething1() {
		this.subSystem1.method1();
		this.subSystem2.method2();
		this.subSystem3.method3();
	}
}


// 子系统们
class SubSystem1 {
	public void method1() {
		System.out.println("SubMethod1.method1 execute");
	}
}

class SubSystem2 {
	public void method2() {
		System.out.println("SubMethod2.method2 execute");
	}
}

class SubSystem3 {
	public void method3() {
		System.out.println("SubMethod3.method3 execute");
	}
}

应用场景

在这里插入图片描述

适配器模式

电压的转换 220V的电压给36V的手机充电 需要一个适配器对电压的转换
这里的适配器也是类似道理
在这里插入图片描述
在这里插入图片描述

代码实现 对象的识别器模式

package com.luyi.designpattern.adapter;

/**对象识别器模式
 * @author 卢意
 * @create 2021-01-03 15:24
 */
public class AdapterTest {
	public static void main(String[] args) {
		Adaptee adaptee = new Adaptee();
		Adapter adapter = new Adapter(adaptee);
		adapter.output5V();
		// result: 原始电压 : 220v -> 输出电压 : 5v
	}
}
// 被转换的对象
class Adaptee {
	// 输出220v的电压
	public int output220v (){
		return 220;
	}
}
interface Target {
	// 输出5v的电压
	int output5V();
}
class Adapter implements Target {

	// 对象的组和的方式进行适配器转换
	private Adaptee adaptee;

	public Adapter (Adaptee adaptee) {
		this.adaptee = adaptee;
	}

	@Override
	public int output5V() {
		int i = adaptee.output220v();
		// ........ 处理
		System.out.println(String.format("原始电压 : %dv -> 输出电压 : %dv", i,5));
		return 5;
	}
}

代码实现 类的识别器模式 对接口会有污染

package com.luyi.designpattern.adapter.v2;

/**
 * 类的识别器  缺点 对接口有污染
 * @author 卢意
 * @create 2021-01-03 15:52
 */
public class AdapterTest2 {
	public static void main(String[] args) {
		Adapter adapter = new Adapter();
		adapter.output5V(); // 当前的adapter 不仅可以output5V 还可以 output220V 对接口产生污染
		//原始电压 : 220v -> 输出电压 : 5v
	}
}

// 被转换的对象
class Adaptee {
	// 输出220v的电压
	public int output220v (){
		return 220;
	}
}
interface Target {
	// 输出5v的电压
	int output5V();
}

class Adapter extends Adaptee implements Target{

	@Override
	public int output5V() {
		int i = output220v();
		// ........ 处理
		System.out.println(String.format("原始电压 : %dv -> 输出电压 : %dv", i,5));
		return 5;
	}
}

应用场景

在这里插入图片描述

装饰者模式

符和软件开发的开闭原则 对扩展开放 对修改关闭
在这里插入图片描述
在这里插入图片描述

代码实现

package com.luyi.designpattern.decoration;

/**
 * 装饰者模式
 * @author 卢意
 * @create 2021-01-03 16:09
 */
public class DecorationTest {
	public static void main(String[] args) {
		Component component = new ConcreateComponent(); // 最初始的功能
		component.operation();
		// 拍照
		System.out.println("扩展美颜效果功能================");
		Component component1 = new ConcreateDecorator(new ConcreateComponent()); // 最初始的功能
		component1.operation();
		// 拍照
		//添加美颜效果

		System.out.println("扩展滤镜功能================");
		Component component2 = new ConcreateDecorator2(new ConcreateDecorator(new ConcreateComponent())); // 最初始的功能
		component2.operation();
		//拍照
		//添加美颜效果
		//添加的滤镜功能

	}
}
interface Component {
	void operation ();
}

class  ConcreateComponent implements Component {

	@Override
	public void operation() {
		System.out.println("拍照");
	}
}
abstract class Decoration implements Component {
	Component component;

	public Decoration(Component component) {
		this.component = component;
	}
}

class ConcreateDecorator extends Decoration {

	public ConcreateDecorator(Component component) {
		super(component);
	}

	@Override
	public void operation() {
		component.operation();
		System.out.println("添加美颜效果");
	}
}

class ConcreateDecorator2 extends Decoration {

	public ConcreateDecorator2(Component component) {
		super(component);
	}

	@Override
	public void operation() {
		component.operation();
		System.out.println("添加的滤镜功能");
	}
}

应用场景

在这里插入图片描述

策略模式

在这里插入图片描述


第二个版本
在这里插入图片描述

代码实现 非策略模式 如果一直有新的僵尸 就会一直继承再重写 代码会越积越大 越复杂

package com.luyi.designpattern.strategy;

/**
 * @author 卢意
 * @create 2021-01-03 18:02
 */
public class ZombieTest {
	public static void main(String[] args) {
		AbstractZombie normalZombie = new NormalZombie();
		AbstractZombie flaZombie = new FlagZombie();

		normalZombie.display();
		normalZombie.move();
		normalZombie.attack();

		System.out.println("------------------");
		flaZombie.display();
		flaZombie.move();
		flaZombie.attack();
	}
}

abstract class AbstractZombie {
	public abstract void display();

	public void attack() {
		System.out.println("咬");
	}

	public void move() {
		System.out.println("一步一步移动");
	}
}

// 普通僵尸
class NormalZombie extends AbstractZombie {

	@Override
	public void display() {
		System.out.println("我是普通僵尸");
	}
}

// 旗手僵尸
class FlagZombie extends AbstractZombie {

	@Override
	public void display() {
		System.out.println("我是旗手僵尸");
	}
}

class BigHeadZombie extends AbstractZombie  {

	@Override
	public void display() {
		System.out.println("我的大头僵尸");
	}

	@Override
	public void attack() {
		System.out.println("头撞");
	}

}

// 可能有的僵尸的攻击方式也是头撞 但是移动方式不同
class XxxZombie extends BigHeadZombie {
	@Override
	public void move() {
		System.out.println("xxxx");
	}
}


代码实现 策略模式

package com.luyi.designpattern.strategy.v2;

/**
 * 策略模式
 * @author 卢意
 * @create 2021-01-03 18:16
 */
public class ZombieTest {
	public static void main(String[] args) {
		// 先分析稳定的部分和变化的部分 僵尸的行为(攻击 移动)是稳定的 但是移动和攻击的方式是变化的

		Zombie zombie = new NormalZombie();
		zombie.display();
		zombie.move();
		zombie.attack();
		//我是普通僵尸
		//一步一步的移动
		//咬你

		zombie.setAttack1(new HitAttack());
		zombie.attack();
		// 换攻击方式
		//我是普通僵尸
		//一步一步的移动
		//打你
	}
}

interface Movable {
	void move();
}
interface Attack {
	void attack();
}
abstract class Zombie {
	abstract public void display();
	Movable movable;
	Attack attack1;
	abstract void move();
	abstract void attack();

	public Movable getMovable() {
		return movable;
	}

	public Zombie(Movable movable, Attack attack1) {
		this.movable = movable;
		this.attack1 = attack1;
	}

	public void setMovable(Movable movable) {
		this.movable = movable;
	}

	public Attack getAttack1() {
		return attack1;
	}

	public void setAttack1(Attack attack1) {
		this.attack1 = attack1;
	}
}

// 定义一种移动方式的实现类  一步一步的移动
class StepByStepMove implements Movable {

	@Override
	public void move() {
		System.out.println("一步一步的移动");
	}
}

// 定义一种攻击的实现类
class BiteAttack implements  Attack {

	@Override
	public void attack() {
		System.out.println("咬你");
	}
}

class HitAttack implements Attack {

	@Override
	public void attack() {
		System.out.println("打你");
	}
}

// 普通僵尸
class NormalZombie extends Zombie {

	public NormalZombie() {
		super(new StepByStepMove(), new BiteAttack());

	}

	public NormalZombie(Movable movable, Attack attack1) {
		super(movable, attack1);
	}

	@Override
	public void display() {
		System.out.println("我是普通僵尸");
	}

	@Override
	void move() {
		movable.move();
	}

	@Override
	void attack() {
		attack1.attack();
	}
}

class FlagZombie extends Zombie {

	public FlagZombie() {
		super(new StepByStepMove(), new BiteAttack());

	}

	public FlagZombie(Movable movable, Attack attack1) {
		super(movable, attack1);
	}

	@Override
	public void display() {
		System.out.println("我是骑手僵尸");
	}

	@Override
	void move() {
		movable.move();
	}

	@Override
	void attack() {
		attack1.attack();
	}
}

应用

Arrays类的Comparable方法

模板模式

和工厂方法模式的区别是
工厂方法模式是用于创建产品的在创建时才会选择具体实现(在创建产品的时候才会确定创建哪一个产品)
而模板模式 执行某一个步骤(方法)延迟到子类
在这里插入图片描述
在这里插入图片描述

代码实现

package com.luyi.designpattern.templatemethod;

/**
 * @author 卢意
 * @create 2021-01-03 19:12
 */
public class TemplateMethod {
	public static void main(String[] args) {
		AbstractClass abstractClass = new SubClass();
		abstractClass.operation();
	}
}

abstract class AbstractClass {
	public void  operation() {
		// open
		// sql
		//close
		System.out.println("预处理");
		System.out.println("解析数据...");
		System.out.println("step1");
		// 由子类实现的方法 (可以理解为用户自定义方法)
		templateMethod();
	}

	abstract protected void templateMethod();
}

class SubClass extends AbstractClass {

	@Override
	protected void templateMethod() {
		System.out.println("SubClass executed ");
	}
}

应用场景

在这里插入图片描述

观察者模式

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

代码实现

package com.luyi.designpattern.observe;

import java.util.ArrayList;
import java.util.List;

/**
 * @author 卢意
 * @create 2021-01-03 19:25
 */
public class ObserveTest {
	public static void main(String[] args) {
		Subject subject = new Subject();
		subject.addObserver(new Task1());
		subject.addObserver(new Task2());
		subject.notifyObserver("haha");
		// receive1 : haha
		//receive2 : haha
	}
}

// 主题对象
class Subject {
	// 容器 存放观察者对象
	private List<Observer> container = new ArrayList<>();
	// add 方法
	public void addObserver(Observer observer) {
		container.add(observer);
	}
	// remove 方法
	public void remove(Observer observer) {
		container.remove(observer);
	}

	// 通知观察者已经发生变化
	public void notifyObserver(Object o) {
		for (Observer observer : container) {
			observer.update(o);
		}
	}
}

// 观察者
interface Observer {
	void update(Object object);
}

// 更新的任务
class Task1 implements Observer {

	@Override
	public void update(Object object) {
		System.out.println("receive1 : "+ object );
	}
}

// 更新的任务
class Task2 implements Observer {

	@Override
	public void update(Object object) {
		System.out.println("receive2 : "+ object );
	}
}

应用场景

在这里插入图片描述

责任链模式

在这里插入图片描述
在这里插入图片描述
**如果有新的限制 直接在代码里添加会造成代码的过于复杂 冗余 也有可能导致原来的代码出错 所以需要链路式的重构 **
在这里插入图片描述

代码实现

package com.luyi.designpattern.chainofresponsibility;

/**
 * @author 卢意
 * @create 2021-01-03 19:48
 */
public class ChainOfResponsibility {
	public static void main(String[] args) {
		Request request = new Request.RequestBuilder().isFrequentOk(true).Logined(true).builder();

		RequestFrequentHandler requestFrequentHandler = new RequestFrequentHandler(new loginHandler(null));
		if (requestFrequentHandler.process(request)) {
			System.out.println("请求成功");
		}
		else  {
			System.out.println("请求失败");
		}
		//访问频率控制
		//登录验证控制
		//请求成功
			

	}
}

// 用于封装请求的路径
class Request {
	private boolean logined; //登录了没
	private boolean frequentOk; //请求频率
	private boolean isPermits; // 访问权限
	private boolean containSensitiveWord; //敏感词
	private String requestBody;

	public Request(boolean logined, boolean frequentOk, boolean isPermits, boolean containSensitiveWord) {
		this.logined = logined;
		this.frequentOk = frequentOk;
		this.isPermits = isPermits;
		this.containSensitiveWord = containSensitiveWord;
	}

	public Request() {
	}

	static class RequestBuilder {
		private boolean logined; //登录了没
		private boolean frequentOk; //请求频率
		private boolean isPermits; // 访问权限
		private boolean containSensitiveWord; //敏感词

		public RequestBuilder Logined(boolean logined) {
			this.logined = logined;
			return this;
		}


		public RequestBuilder isFrequentOk(boolean frequentOk) {
			this.frequentOk = frequentOk;
			return this;
		}

		public RequestBuilder isPermits(boolean isPermits) {
			this.isPermits = isPermits;
			return this;
		}


		public RequestBuilder isContainSensitiveWord(boolean containSensitiveWord) {
			this.containSensitiveWord = containSensitiveWord;
			return this;
		}

		public Request builder() {
			return new Request( logined,  frequentOk,  isPermits,  containSensitiveWord);
		}

	}

	public boolean isLogined() {
		return logined;
	}

	public boolean isFrequentOk() {
		return frequentOk;
	}

	public boolean isPermits() {
		return isPermits;
	}

	public boolean isContainSensitiveWord() {
		return containSensitiveWord;
	}

}

abstract class Handler {
	Handler next; // 下一个节点

	public Handler(Handler next) {
		this.next = next;
	}

	public Handler getNext() {
		return next;
	}

	public void setNext(Handler next) {
		this.next = next;
	}

	abstract boolean process(Request request);
}

class  RequestFrequentHandler extends Handler {

	public RequestFrequentHandler(Handler next) {
		super(next);
	}

	@Override
	boolean process(Request request) {

		System.out.println("访问频率控制");
		if (request.isFrequentOk()) {
			Handler next = getNext();
			if (next == null) {
				return true;
			}
			if ( !next.process(request)) {
				return false;
			} else {
				return true;
			}
		}
		return false;
	}
}

class loginHandler extends Handler {

	public loginHandler(Handler next) {
		super(next);
	}

	@Override
	boolean process(Request request) {
		System.out.println("登录验证控制");
		if (request.isLogined()) {
			Handler next = getNext();
			if (next == null) {
				return true;
			}
			if ( !next.process(request)) {
				return false;
			} else {
				return true;
			}
		}
		return false;
	}
}

应用场景

在这里插入图片描述

面向对象软件设计原则SOLID

单一职责原则

在这里插入图片描述

开闭原则在这里插入图片描述

里氏替换原则

在这里插入图片描述

接口隔离原则

在这里插入图片描述

依赖倒置原则

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值