这里写目录标题
单例设计模式
懒汉模式 注释写的很清楚
代码实现
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;
}
}