【个人技术经验及开发技巧分享】 【个人技术经验及开发技巧分享】
首页
  • 操作系统初识
  • JAVA基础
  • JVM
  • 开发框架
  • Redis
  • Zookeeper
  • 消息中间件
  • 持久化
  • 算法
  • 网络
  • 系统架构
  • 并发编程
  • 框架
  • 开发杂货
  • 线上排查
  • 技巧备忘
  • 部署指南
  • 版本管理
  • 工作流程
  • 发版流程
  • 友情链接
  • 网站备忘
  • 在线工具
  • 学习
  • 各种云
  • 应用下载

Louis

首页
  • 操作系统初识
  • JAVA基础
  • JVM
  • 开发框架
  • Redis
  • Zookeeper
  • 消息中间件
  • 持久化
  • 算法
  • 网络
  • 系统架构
  • 并发编程
  • 框架
  • 开发杂货
  • 线上排查
  • 技巧备忘
  • 部署指南
  • 版本管理
  • 工作流程
  • 发版流程
  • 友情链接
  • 网站备忘
  • 在线工具
  • 学习
  • 各种云
  • 应用下载
  • 操作系统初识

  • JAVA基础

    • 理论概念
    • ThreadLocal
    • volatile关键字
    • 数据结构
    • 并发编程
    • 多线程
    • 设计模式
      • 1 责任链模式
      • 2 建造者模式
      • 3 工厂模式(结合注解)
      • 4 模版方法模式
      • 5 策略模式
      • 6 单例模式
        • 6.1 懒汉(线程不安全)
        • 6.2 懒汉(线程安全 | 性能低)
        • 6.3 懒汉(线程安全 | 性能高)
        • 6.4 饿汉
        • 6.5 静态内部类方式
        • 6.6 枚举
    • 常见基础问题
  • JVM

  • 开发框架

  • Redis

  • Zookeeper

  • 消息中间件

  • 持久化

  • 算法

  • 网络

  • 系统架构

  • 学习笔记
  • JAVA基础
luoxiaofeng
2022-04-28
目录

设计模式

# 设计模式

# 1 责任链模式

为了避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。可以通过数据链表来实现职责链模式。

public class ChainOfResponsibilityPattern {
  public static void main(String[] args) {
    //组装责任链
    Handler handler1 = new ConcreteHandler1();
    Handler handler2 = new ConcreteHandler2();
    Handler handler3 = new ConcreteHandler3();
    handler1.setNext(handler2);
    handler2.setNext(handler3);
    //提交请求
    handler1.handleRequest("three");
  }
}

//抽象处理者角色
abstract class Handler {
  private Handler next;

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

  public Handler getNext() {
    return next;
  }

  //处理请求的方法
  public abstract void handleRequest(String request);
}

//具体处理者角色1
class ConcreteHandler1 extends Handler {
  public void handleRequest(String request) {
    System.out.println("查询one...");
    if (request.equals("one")) {
      System.out.println("具体处理者1负责处理该请求!");
    } else {
      if (getNext() != null) {
        getNext().handleRequest(request);
      } else {
        System.out.println("没有人处理该请求!");
      }
    }
  }
}

//具体处理者角色2
class ConcreteHandler2 extends Handler {
  public void handleRequest(String request) {
    System.out.println("查询two...");
    if (request.equals("two")) {
      System.out.println("具体处理者2负责处理该请求!");
    } else {
      if (getNext() != null) {
        getNext().handleRequest(request);
      } else {
        System.out.println("没有人处理该请求!");
      }
    }
  }
}

//具体处理者角色3
class ConcreteHandler3 extends Handler {
  public void handleRequest(String request) {
    System.out.println("查询three...");
    if (request.equals("three")) {
      System.out.println("具体处理者3负责处理该请求!");
    } else {
      if (getNext() != null) {
        getNext().handleRequest(request);
      } else {
        System.out.println("没有人处理该请求!");
      }
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76

打印结果

查询one...
查询two...
查询three...
具体处理者3负责处理该请求!
1
2
3
4

# 2 建造者模式

将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。它将变与不变相分离,即产品的组成部分是不变的,但每一部分是可以灵活选择的。

public class Computer {
  private final String cpu;//必须
  private final String ram;//必须
  private final int usbCount;//可选
  private final String keyboard;//可选
  private final String display;//可选

  private Computer(Builder builder) {
    this.cpu = builder.cpu;
    this.ram = builder.ram;
    this.usbCount = builder.usbCount;
    this.keyboard = builder.keyboard;
    this.display = builder.display;
  }

  public static class Builder {
    private String cpu;//必须
    private String ram;//必须
    private int usbCount;//可选
    private String keyboard;//可选
    private String display;//可选

    public Builder(String cup, String ram) {
      this.cpu = cup;
      this.ram = ram;
    }

    public Builder setUsbCount(int usbCount) {
      this.usbCount = usbCount;
      return this;
    }

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

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

    public Computer build() {
      return new Computer(this);
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
Computer computer=new Computer.Builder("m1","MAC")
        .setDisplay("14寸")
        .setKeyboard("magic")
        .setUsbCount(0)
        .build();
1
2
3
4
5

# 3 工厂模式(结合注解)

提示

@ConditionalOnBean:当IOC容器中有 billOperationProcessor 接口的实现类时,才会向容器中注入 BillOperationProcessorFactory

@Slf4j
@Component
@ConditionalOnBean(BillOperationProcessor.class)
public class BillOperationProcessorFactory implements ApplicationRunner, ApplicationContextAware {

	/**
	 * 运行上下文
	 */
	private ApplicationContext applicationContext;

	/**
	 * 处理类型缓存 Map
	 */
	private final Map<SqlCommandType, BillOperationProcessor<?>> billOperationProcessorMap = new HashMap<>(SqlCommandType.values().length);

	/**
	 * 获取处理类
	 *
	 * @param operation 处理类型
	 * @return 处理类
	 */
	public BillOperationProcessor getBillOperationHandler(SqlCommandType operation) {

		BillOperationProcessor billOperationProcesser = billOperationProcessorMap.get(operation);
		if (Objects.isNull(billOperationProcesser)) {
			log.warn("通过{}获取对应的处理类为空", operation);
			throw new RuntimeException("通过" + operation + "获取对应的处理类为空");
		}
		return billOperationProcesser;
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.applicationContext = applicationContext;
	}

	/**
	 * 项目启动成功, 注册处理类
	 * @param args 参数
	 */
	@Override
	public void run(ApplicationArguments args) {
		log.info("处理工厂注册处理类开始");
		Map<String, BillOperationProcessor> beansOfType = applicationContext.getBeansOfType(BillOperationProcessor.class);
		if (CollectionUtils.isEmpty(beansOfType)) {
			return;
		}
		beansOfType.forEach((beanName, bean) -> {
			BillOperation annotation = bean.getClass().getAnnotation(BillOperation.class);
			if (Objects.isNull(annotation)) {
				log.info("{} bean 的运单操作类型对应操作类型未指定", bean.getClass().getName());
				return;
			}
			billOperationProcessorMap.put(annotation.opType(), bean);
		});
		log.info("处理工厂注册处理类注册完成, 注册了{}个处理类", billOperationProcessorMap.size());
		billOperationProcessorMap.forEach((k, v) -> log.info("处理工厂注册了{}处理器", k));
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
public interface BillOperationProcessor<T> {
    
  void billInfoHandler(T billInfo, Map<Integer, List<SpmoBillTransferDTO>> mqSendData);
  
}
1
2
3
4
5
@Slf4j
public abstract class AbstractDispatchBillOperationProcessor implements BillOperationProcessor<DispatchBillModifyDTO> {
  @Override
  public void billInfoHandler(DispatchBillModifyDTO billInfo, Map<Integer, List<SpmoBillTransferDTO>> mqSendData) {
    // ... ...
  }
  protected BillHandlerChain initBillFilterHandler() {
    return null;
  }
  // ... ...
}
1
2
3
4
5
6
7
8
9
10
11
@Component
@BillOperation(opType = SqlCommandType.DISPATCH_WAYBILL_UPDATE)
public class DispatchBillUpdateOperationProcessor extends AbstractDispatchBillOperationProcessor {
  @Override
  protected BillHandlerChain initBillFilterHandler() {
    BillHandlerChain billCancelSignHandlerChain = new BillCancelSignHandlerChain();
    billCancelSignHandlerChain.customerNextBillFilter(new BillModifyHandlerChain());
    return billCancelSignHandlerChain;
  }
}
1
2
3
4
5
6
7
8
9
10
@Component
@BillOperation(opType = SqlCommandType.INSERT)
public class PickBillInsertOperationProcessor extends AbstractPickBillOperationProcessor {
  @Override
  public BillHandlerChain initBillFilterHandler() {
    // 新增只需要考虑结算方式处理链, 不需要设置下游处理链
    return new BillModifyHandlerChain();
  }
}
1
2
3
4
5
6
7
8
9

调用端

@Resource
private BillOperationProcessorFactory billOperationProcessorFactory;
//... ...
billOperationProcessorFactory.getBillOperationHandler(billModify.getOperation()).billInfoHandler(billModify, mqSendData);
1
2
3
4

# 4 模版方法模式

public class TemplateMethodPattern {
  public static void main(String[] args) {
    AbstractClass tm = new ConcreteClass();
    tm.TemplateMethod();
  }
}

//抽象类
abstract class AbstractClass {
  public void TemplateMethod() //模板方法
  {
    SpecificMethod();
    abstractMethod1();
    abstractMethod2();
  }

  public void SpecificMethod() //具体方法
  {
    System.out.println("抽象类中的具体方法被调用...");
  }

  public abstract void abstractMethod1(); //抽象方法1

  public abstract void abstractMethod2(); //抽象方法2
}

//具体子类
class ConcreteClass extends AbstractClass {
  public void abstractMethod1() {
    System.out.println("抽象方法1的实现被调用...");
  }

  public void abstractMethod2() {
    System.out.println("抽象方法2的实现被调用...");
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

打印结果

抽象类中的具体方法被调用...
抽象方法1的实现被调用...
抽象方法2的实现被调用...
1
2
3

# 5 策略模式

传统的实现方式(不用策略模式)

public class Test {
  public Double calculationPrice(String type, Double originalPrice, int n) {

    //中级会员计费
    if (type.equals("intermediateMember")) {
      return originalPrice * n - originalPrice * 0.1;
    }
    //高级会员计费
    if (type.equals("advancePrimaryMember")) {
      return originalPrice * n - originalPrice * 0.2;
    }
    //普通会员计费
    return originalPrice;
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

提示

传统的实现方式,通过传统 if 代码判断。这样就会导致后期的维护性非常差。当后期需要新增计费方式,还需要在这里再加上 if() ,也不符合面向对象设计原则中的开闭原则。

策略模式实现

抽象类策略

public interface MemberStrategy {
    // 一个计算价格的抽象方法
    //price商品的价格 n商品的个数
    public double calcPrice(double price, int n);
}
1
2
3
4
5

具体实现类

// 普通会员 不打折
public class PrimaryMemberStrategy implements MemberStrategy { // 实现策略
  //重写策略方法具体实现功能
  @Override
  public double calcPrice(double price, int n) {
    return price * n;
  }
}
1
2
3
4
5
6
7
8
// 中级会员 10%的折扣
public class IntermediateMemberStrategy implements MemberStrategy {
  @Override
  public double calcPrice(double price, int n) {
    double money = (price * n) - price * n * 0.1;
    return money;
  }
}
1
2
3
4
5
6
7
8
// 高级会员类 20%折扣
public class AdvanceMemberStrategy implements MemberStrategy {
  @Override
  public double calcPrice(double price, int n) {
    double money = price * n - price * n * 0.2;
    return money;
  }
}
1
2
3
4
5
6
7
8

上下文类

/**
 * 负责和具体的策略类交互
 * 这样的话,具体的算法和直接的客户端调用分离了,使得算法可以独立于客户端独立的变化。
 */
public class MemberContext {
  // 用户折扣策略接口
  private MemberStrategy memberStrategy;
  // 注入构造方法
  public MemberContext(MemberStrategy memberStrategy) {
    this.memberStrategy = memberStrategy;
  }
  // 计算价格
  public double qoutePrice(double goodsPrice, int n) {
    // 通过接口变量调用对应的具体策略
    return memberStrategy.calcPrice(goodsPrice, n);
  }

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

测试类

// 测试类
public class Application {
  public static void main(String[] args) {
    // 具体行为策略
    MemberStrategy primaryMemberStrategy = new PrimaryMemberStrategy(); // 接口回调(向上转型)
    MemberStrategy intermediateMemberStrategy = new IntermediateMemberStrategy();
    MemberStrategy advanceMemberStrategy = new AdvanceMemberStrategy();
    // 用户选择不同策略
    MemberContext primaryContext = new MemberContext(primaryMemberStrategy);
    MemberContext intermediateContext = new MemberContext(intermediateMemberStrategy);
    MemberContext advanceContext = new MemberContext(advanceMemberStrategy);
    //计算一本300块钱的书
    System.out.println("普通会员的价格:" + primaryContext.qoutePrice(300, 1));// 普通会员:300
    System.out.println("中级会员的价格:" + intermediateContext.qoutePrice(300, 1));// 中级会员 270
    System.out.println("高级会员的价格:" + advanceContext.qoutePrice(300, 1));// 高级会员240
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 6 单例模式

# 6.1 懒汉(线程不安全)

public class Singleton {
  private static Singleton instance;

  private Singleton() {
  }

  public static Singleton getInstance() {
    if (instance == null) {
      instance = new Singleton();
    }
    return instance;
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

# 6.2 懒汉(线程安全 | 性能低)

public class Singleton {
  private static Singleton instance;

  private Singleton() {
  }

  public static synchronized Singleton getInstance() {
    if (instance == null) {
      instance = new Singleton();
    }
    return instance;
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

# 6.3 懒汉(线程安全 | 性能高)

public class Singleton {
  private volatile static Singleton singleton;

  private Singleton() {
  }

  public static Singleton getSingleton() {
    if (singleton == null) {
      synchronized (Singleton.class) {
        if (singleton == null) {
          singleton = new Singleton();
        }
      }
    }
    return singleton;
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 6.4 饿汉

public class Singleton {
  private static Singleton instance = new Singleton();

  private Singleton() {
  }

  public static Singleton getInstance() {
    return instance;
  }
}
1
2
3
4
5
6
7
8
9
10

# 6.5 静态内部类方式

提示

这种方式能达到双检锁方式一样的功效,但实现更简单。对静态域使用延迟初始化,应使用这种方式而不是双检锁方式。这种方式只适用于静态域的情况,双检锁方式可在实例域需要延迟初始化时使用。

public class Singleton {
  private static class SingletonHolder {
    private static final Singleton INSTANCE = new Singleton();
  }

  private Singleton() {
  }

  public static final Singleton getInstance() {
    return SingletonHolder.INSTANCE;
  }
}
1
2
3
4
5
6
7
8
9
10
11
12

# 6.6 枚举

public enum Singleton {
  INSTANCE;

  public void whateverMethod() {
  }
}
1
2
3
4
5
6
#Java基础
多线程
常见基础问题

← 多线程 常见基础问题→

最近更新
01
SpringBoot
10-21
02
Spring
10-20
03
Sentinel
10-14
更多文章>
Copyright © 2022-2023 Louis | 粤ICP备2022060093号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式