单例模式与责任链模式

Posted AIB程序猿

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单例模式与责任链模式相关的知识,希望对你有一定的参考价值。




前言


https://juejin.im/post/5c7c631b6fb9a049f746eb37

另一篇是关于性能优化的

https://juejin.im/post/5c7e44206fb9a049ac79e8b5

但其实更多的原因是不知道写什么,想了一下。大概是自己这段时间学习的效率不好有关系吧。



单例模式与责任链模式

单例模式

单例模式与责任链模式


  • 饿汉式单例

/**
*饿汉单例模式
*/
private OneModel(){};
private static final OneModel model=new OneModel();
public static OneModel getModel(){
return model;
}
public void work(){
System.out.println("单例模式work()方法");
}
public void rest(){
System.out.println("单例模式rest()方法");
}

顾名思义,就是类出现时就初始化。

  • 懒汉式单例

/**
* DCL单例模式:第一次执行时才被实例化
* 使用最多的单例模式,但是代码比较丑陋.
*/
public class TwoModel {
private TwoModel(){};
private static volatile TwoModel model=null;
public static TwoModel getTwoModel(){
if(model==null){
synchronized (TwoModel.class) {
if(model==null){
model=new TwoModel();
}
}
}
return model;
}
}

所谓懒汉式,就是懒。调用get方法时才实例化对象。这里有个线程安全问题。 需要加类锁。说到锁说一下


类锁与对象锁的区别?

类锁只有一个,对象锁可以有很多歌。对象是实例化的类。


  • 内部类的方式

/**
* 保证线程安全的同时又延迟了单例的实例化
* 推荐使用这种方法
*/
public class ThreeModel {
private ThreeModel(){};
public static ThreeModel getThreeModel(){
return ThreeModelHodeler.Model;
}
private static class ThreeModelHodeler{
private static final ThreeModel Model=new ThreeModel();
}
}


责任链模式

okHttp中的拦截器的部分就是使用责任链模式实现的。简单的责任链模式类图如上。先说说责任链的使用场景。

  • 对多个对象都可以处理同一请求,但具体由哪一个处理则在运行时决定。

  • 在请求处理者不明确的情况下向多个对象中的一个提交一个请求

  • 需要动态指定一组对象处理请求时


具体实现,以请假为例

如果一个学生请假,一天以内老师可以批,7天以内年级可以批,7天以上学校才可以批。但是学校请假只需要找打老师即可。这就是一个简单的责任链模式。


根据类图,发现有几个类

  • 抽象处理者类,用于定义规则。(可以看做是教育局

  • 具体处理者类,规则的执行的执行者。(年级、学校)

  • 请求发起类(老师)


抽象处理者

public abstract class LeaderHandle {
protected LeaderHandle handler;
/**
   *
   * @param day  请假天数
   */
  public final void handleRequest(int day){
System.out.println("handle添加了"+day);
if(day>limit()){
if(handler!=null){
handler.handleRequest(day);
}
}else{
handle(day);
}
}
/**
   * 如果不用交给上一级处理,那就自己处理
   * @param day
   */
  public abstract void handle(int day);
public abstract int limit();
}

    核心在于handleRequest这个方法,当然名字可以随便取。这个方法定义了规则。这个规则是由外部传进来的。然后做了递归(自己调用自己)。这样可以保证如果一个不合适的处理者拿到请求可以传递给下一个处理者。


具体处理者


public class School extends LeaderHandle{

@Override
  public void handle(int day) {
System.out.println("校长给你批了:"+day+"天");
}

@Override
  public int limit() {
return Integer.MAX_VALUE;
}

}
public class GradeLeader extends LeaderHandle{

@Override
  public void handle(int day) {
System.out.println("7天以内的假期年级给你批了:"+day+"天");
}

@Override
  public int limit() {
return 7;
}

}


public class Teacher extends LeaderHandle{

@Override
  public void handle(int day) {
System.out.println("老师批价了:"+day+"天");
}

@Override
  public int limit() {
return 1;
}

}


三个具体处理类,把具体规则回传给了抽象处理类当做条件判断具体具体会调那个类的handle方法。


请求类


public class ChainMain {
public static void main(String[] args) {
System.out.println("责任链模式");      Teacher teacher = new Teacher();
GradeLeader gradeLeader = new GradeLeader();
teacher.handler=gradeLeader;
School school = new School();
gradeLeader.handler=school;
//请假只需要跟老师说
     teacher.handleRequest(2);
}
}


具体代码执行过程说一下:
    由teacher发起处理消息的操作,所以一开始是teacher带着他的权限limit(批假天数)去调用handleRequest方法。


    发现不合适便调用handler的handleRequest,由于一开始teacher指定了下一级是gradeleader(上面的代码直接指定,有些代码会写个set方法)。所以调用的是gradeleader的handleRequest的方法。发现条件合适便回调到了gradeleader的handle方法。


    所以会发现okhttp拦截器的地方也是类似的实现方式,不同的地方在于规则处,比如有些需要两个类同时拿到请求,这个时候改一下判断语句就好。整个责任难模式必须要有的是

1、具体实现类必须指定下一级

2、判断处理规则,并且调用下一级的处理方法


题外话

    抖音上刷到的视频说的大概意思是,常常说得到了什么什么就幸福的人常常是不会幸福的,因为人生不如意十有八九。只有今天你觉得幸福了才会幸福。

    就比如我们期待国庆有7天的假期,觉得有7天假期才叫幸福,但是往往有些人一开始放假就开始算还有6天上班、过了一天又想着还有5天上班……所以我们不要期望明天怎么怎么样,因为今天也是昨天的明天。我们应该要一直保持幸福感。



   

AIB程序猿

长按扫描二维码关注


记录编程与生活的点点滴滴









以上是关于单例模式与责任链模式的主要内容,如果未能解决你的问题,请参考以下文章

设计模式

设计模式之责任型接口型模式

13-Python与设计模式--责任链模式

设计模式之——单例模式

设计模式之策略模式与责任链模式详解和应用

如何在C#/.NET Core中使用责任链模式