单例、责任链、工厂模式入门笔记+理解

1. Singleton单例模式

只需要一个实例

构造器私有

1.1 饿汉式

  • JVM保证了线程安全

  • 缺点:类装载时就完成了实例化,不管有没有用

public class Hungry() {
  private static final Hungry INSTANCE = new HUNGRY();
  
  private Hungry() {}
  
  public static Hungry getInstance() { return INSTANCE; }
}

1.2 懒汉式

1.2.1 用的时候再实例化:

// 缺点:线程不安全
public class Lazy01() {
  private static Lazy01 INSTANCE;
  
  private Lazy01() {}
  
  public static Lazy01 getInstance() {
    if (INSTANCE == null) { // 几个线程可以同时判断为null,从而创建多个实例
      try {
        Thread.sleep(1);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      INSTANCE = new Lazy01();
    }
    return INSTANCE;
  }
}

1.2.2 给 getInstance() 加锁:

public class Lazy02() {
  private static Lazy02 INSTANCE;
  
  private Lazy02() {}
  // 缺点:锁的粒度太粗
  public static synchronized Lazy02 getInstance() {
    
    // ...
    // 很多业务逻辑
    // ...
    
    if (INSTANCE == null) {
      try {
        Thread.sleep(1);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      INSTANCE = new Lazy02();
    }
    return INSTANCE;
  }
}

1.2.3 在实例化的地方加锁:

public class Lazy03() {
  private static Lazy03 INSTANCE;
  
  private Lazy03() {}
  public static Lazy03 getInstance() {
    
    // ...
    // 很多业务逻辑
    // ...
    
    if (INSTANCE == null) {
      // 缺点:还是线程不安全
      synchronized (Lazy03.class) {
        try {
          Thread.sleep(1);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        INSTANCE = new Lazy03();
      }
    }
    return INSTANCE;
  }
}

1.2.4 DCL (Double Check Lock)

public class DCL() {
  private static volatile DCL INSTANCE;
  
  private DCL() {}
  public static Lazy03 getInstance() {
    
    // ...
    // 很多业务逻辑
    // ...
    
    if (INSTANCE == null) { // 这层与线程安全无关,是为了提高效率
      synchronized (DCL.class) {
        if (INSTANCE == null) { // 双重检查
          try {
            Thread.sleep(1);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
          INSTANCE = new DCL();
        }
      }
    }
    return INSTANCE;
  }
}
  • DCL需不需要加 volatile ?

对象创建的过程(大体):

  1. 分配内存 (对象的成员变量(这里是INSTANCE)被赋予默认值)
  2. 初始化 -- INSTANCE被赋予真实值
  3. 建立关联 -- 将变量名指向INSTANCE

2,3可能出现指令重排序的现象,也就是说,一个线程中对象在半初始化的时候就与INSTANCE建立联系了,另一个线程发现INSTANCE不为空,则直接拿到了半初始化的INSTANCE,所以需要 volatile 来禁止指令的重排序!

1.3 静态内部类

public class Single() {
  private Single() {}
  
  // Single的静态内部类在Single加载时不会被加载
  private static class SingleHolder {
    // 只有在Single类的内部才能调用Single的私有构造
    private final static Single INSTANCE = new Single();
  }
  // 只有调用此方法才会加载SingleHolder,并且return的是SingleHolder中的静态变量
  // JVM保证Class类只会被加载一次,保证单例
  public static Single getInstance() { return SingleHolder.INSTANCE; }
}

1.4 枚举(*)

public enum Single02() {
  // 不仅线程同步,还可以防止反序列化
  INSTANCE;
  public void m() {}
  
  public static void main(Stringp[] args) {
    Single02.INSTANCE;
  }
}

后期可以交给Spring来构造单例的Bean

2. 责任链模式

2.1 基本思想

将一条message经过一系列过滤审查程序后加入数据库

// 首先有一个过滤器接口
class interface Filter {
  boolean doFilter(String msg);
}

// 一些过滤器实现
class EncodingCharacterFilter implements Filter {
  public boolean doFilter(String msg) {
    ...
    return true;
  }
}

class SensitiveFilter implements Filter {
  // 在一些过滤器中,若检测到某些元素,则直接放弃将这条信息加入数据库
  public boolean doFilter(String msg) {
    if (...) { return false; }
    return true;
  }
}

class OtherFilter01 implements Filter {...}
class OtherFilter02 implements Filter {...}
// 因为是一系列过滤器,所以将这些filter放在一个filterChain上
class FilterChain implements Filter {
  List<Filter> filters;
  
  public Filter() { this.filters = new ArrayList<>(); }
  
  public void addFilter(Filter filter) { this.filters.add(filter); }
  
  // 遍历chain上的所有filter,若其中一个filter返回false,则直接停止
  public boolean doFilter(String msg) {
    boolean flag = true;
    for (Filter f : this.filters) {
      flag = f.doFilter(msg);
      if (!flag) { return flag; }
    }
    return flag;
  }
}
public static void main(String[] args) {
  FilterChain fc01 = new FilterChain();
  fc01.addFilter(new EncodingCharacterFilter());
  fc01.addFilter(new SensitiveFilter());
  
  FilterChain fc02 = new FilterChain();
  fc02.addFilter(new OtherFilter01());
  fc02.addFilter(new OtherFilter02());
  
  // 这里因为FilterChain本身也实现了Filter接口,所以一整个FilterChain也可以
  // 被加入到另一个FilterChain中
  fc01.addFilter(fc02);
  String msg = "I want a bomb!"
  fc01.doFilter(msg);
}

2.2 责任链在javax.servlet中的(粗略)实现方式:

// 这个类实现了FilterChain接口
public final class ApplicationFilterChain implements FilterChain
// 其中的这个方法接受request和response
// 并在做出一些判读后,调用internalDoFilter()方法
public void doFilter(ServletRequest request, ServletResponse response) {
  if (...) {
    ...
  } else {
    this.internalDoFilter(request, response);
  }
}
private void internalDoFilter(ServletRequest request, ServletResponse response) { 
  
  // 先判断执行到哪一个filter了
  if (this.pos < this.n) {// 若还没有执行完
    ...
    // 从Filter的list中那Filter,并increment pos
    ApplicationFilterConfig filterConfig = this.filters[this.pos++];
    ...
    Filter filter = filterConfig.getFilter();
    ...
    // 拿到Filter后调用Filter的doFilter()方法
    // *这里chain会将自己作为参数传入doFilter
    filter.doFilter(request, response, this);
  } else {
    // 若还执行完了
    // 执行servlet
    this.servlet.service(request, response);
  }
}
// 在Filter的doFilter中,完成过滤逻辑后
// 会用被传入的FilterChain调用doFilter(),进行下一个过滤器
// 而这时chain中的pos已经是被加一了的
// 实现了过滤器的遍历
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
  ...
  // **这里若在重写时不调用chain.doFilter
  // 过滤终止,所以就不用return boolean了
  chain.doFilter(request, response);
}

2.3 递归思想

需求:先按1,2,3的顺序处理request请求,再按3,2,1的顺序处理response响应。


class interface Filter {
  void doFilter(Request req, Response resp, FilterChain chain);
}

class FilterChain implements Filter {
  private int pos = 0;
  private List<Filter> filters = ArrayList<>();
  
  public void doFilter(Request req, Response resp, FilterChain chain) {
    if (this.pos > filters.size()) { return; }
    filters.get(pos++).doFilter(req, resp, this);
  }
}

class FilterImpl01 implements Filter {
  public void doFilter(Request req, Response resp, FilterChain chain) {
    processRequest(req);
    chain.doFilter(req, resp, chain);
    processResponse(resp);
  }
}

class FilterImpl02 implements Filter {...}
class FilterImpl03 implements Filter {...}
public static void main(String[] args) {
  FilterChain fc = new FilterChain();
  fc.add(new FilterImpl01);
  fc.add(new FilterImpl02);
  fc.add(new FilterImpl03);
  fc.doFilter(req, resp, fc);
}

3. Factory工厂模式

3.1 SimpleFactory

不是一种设计模式!

场景:需要通过条件判断来实例化某一个对象

if ("car".equals(name)) {
  Vehicle vehicle = new Car();
} else if ("plane".equals(name)) {
  Vehicle vehicle = new Plane();
} else if ("Tank".equals(name)) {
  Vehicle vehicle = new Tank();
}         

如果在方法中像这样写死,难以维护。可以将这个实例化的过程抽出来

class SimpleVehicleFactory {
  Vehicle vehicle;
  
  public Vehicle create(String name) {
    if ("car".equals(name)) {
      vehicle = new Car();
    } else if ("plane".equals(name)) {
      vehicle = new Plane();
    } else if ("Tank".equals(name)) {
      vehicle = new Tank();
    }
      return vehicle;
  }
}

这样若程序中有多处使用这个实例化的过程,只需要修改这个工厂内方法一处的代码。

3.2 Factory Method Pattern

  • 一个抽象类(Creator)中有对于另一个类(Product)的实例化与使用,在Creator中,实现所有使用了product的方法,但将实例化Product的方法变成抽象的方法,并将实现这个抽象方法的任务交给各个Creator的子类ConcreteCreator。

  • 在下面的例子中,VehicleStore的test()方法需要先将vehicle实例化,再使用vehicle的各个方法。那么具体是哪一种vehicle呢?VehicleStore只规定了在vehicle实例化后如何使用vehicle对象而将vehicle的实例化过程,交给子类去实现,它的各个子类,只需要实现create()这个抽象方法就可以实例化并使用具体的vehicle。

  • 将生产方法(实例化的过程)抽象并交给子类去实现的这种模式就叫做Factory Method Pattern,这里create() 就是the factory method。这种模式,分离了对象的创建和使用 -- test()方法并不知道它所使用的vehicle究竟是具体的哪一种。

    The Factory Method Pattern defines an interface for creating an object, but lets subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.

  • 一个具体的Store,如CarStore,从原来需要依赖具体的Car对象,到如今只需要依赖Vehicle的abstract对象;一个具体的Car对象,也需要依赖Vehicle的abstract对象。这样就做到了依赖反转,Dependency Inversion。

  • 这个模式的好处是,扩展更多的ConcreteProduct非常的容易(扩展更多的vehicle种类),只需要一个继承Vehicle的类和一个继承VehicleStore并实现create()方法的类,并不对原有的代码进行任何修改。

// Product
public abstract class Vehicle {
  String name;
  
  void fillGas();
  
  void drive();
  
  void pullOver();
} 

// ConcreteProduct
public class Car extends Vehicle {
  String name = "car";
}

public class Plane extends Vehicle {...}
public class Tank extends Vehicle {...}
// Creator
public abstract class VehicleStore {
  public void testVehicle() {
    Vehicle vehicle = this.create();
    vehicle.fillGas();
    vehicle.drive();
    vehicle.pullOver();
  }
  // 将生产过程交给子类
  protected abstract Vehicle create();
}

// ConcreteCreator
public class CarStore extends VehicleStore {
  Vehicle create() {
    return new Car();
  }
}

public class PlaneStore extends VehicleStore {
  Vehicle create() {
    return new Plane();
  }
}

public class TankStore extends VehicleStore {...}
public static void main(String[] args) {
  VehicleStore store = new CarStore();
  store.test();
}

3.3 Abstract Factory Pattern

  • 一个武装人员需要一把步枪,一把手枪和一把机枪,但一个警察和一个恐怖分子所需的这三把武器具体的种类都不一样,如警察的步枪为M416,但恐怖分子的步枪为AKM。还有可能有其他种类的武装人员,如特种兵,劫匪等,但他们作为武装人员,都需要一把步枪,一把手枪和一把机枪。

  • 所以我们需要一个接口(creator),这个接口规定了我们需要生产哪些抽象类(Product)(如,需要一把步枪,一把手枪和一把机枪),而这个接口的实现类(ConcreteCreator)实现这些生产方法,生产出抽象类的具体类(ConcreteProduct),如警察的接口实现类户生产M416作为步枪,P1911作为手枪,M249作为机枪。

  • 这个模式就是抽象工厂模式

    An Abstract Factory gives us an interface for creating a family of products.

    That allows us to implement a variety of factories that produce products meant for different contexts—such as different regions, different operating systems, or different look and feels.

  • 缺点是接口规定好了需要哪些抽象类,若要添加抽象类,就需要修改所有接口的实现类。

// 接口规定了生产哪些抽象类
public interface WeaponFactory {
  AR createAR();
  
  Pistol createPistol();
  
  MachineGun createMachineGun();
}
// 抽象类和继承他们的一些具体的类
public abstract class AR {}
public class AKM extends AR {}
public class M416 extens AR {}

public abstract class Pistol {}
public class DesertEagle extends Pistol {}
public class P1911 extends Pistol {}

public abstract class MachineGun {}
public class M249 extends MachineGun {}
public class Gantling extends MachineGun {}
public class PoliceWeaponFactory implements WeaponFactory {
  public AR createAR() {
    return new M416();
  }
  
  public Pistol createPistol() {
    return new P1911();
  }
  
  public MachineGun createMachineGun() {
    return M248;
  }
}

public class TerroristWeaponFactory implements WeaponFactory {
  public AR createAR() {
    return new AKM();
  }
  
  public Pistol createPistol() {
    return new DesertEagle();
  }
  
  public MachineGun createMachineGun() {
    return new Gatline();
  }
}
// 只需要修改工厂的实现类,就可以武装不同的人员
public void arm(Man man) {
  WeaponFactory factory = new PoliceWeaponFactory();
  man.AR = factory.createAR();
  man.pistol = factory.createPistol();
  man.machineGun = factory.createMachineGun();
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容