【设计模式】

  • 创建型(单例/工厂/生成器)
  • 行为型(观察者/迭代器/策略(线程池拒绝策略))
  • 结构型(代理/适配器/装饰者)
  • Spring中的单例模式(BeanFactory懒加载、ApplicationContext饿汉模式)
  • 设计原则(单一责任、开放封闭、接口分离、里氏替换、依赖倒置)

【手写题】

  • LRU
  • 生产者消费者
  • 奇数偶数交替打印

单例模式:
Ⅰ 懒汉式-线程不安全
Ⅱ 饿汉式-线程安全
Ⅲ 懒汉式-线程安全(synchronized)
Ⅳ 双重校验锁-线程安全

public class Singleton{
    private volatile static Singleton uniqueInstance;

    private Singleton() {
    }

    public static Singleton getUniqueInstance() {
        if (uniqueInstance == null) {
            synchronized (Singleton.class) {
                if (uniqueInstance == null) {
                    uniqueInstance = new Singleton();
                }
            }
        }
        return uniqueInstance;
    }
}

Ⅴ 静态内部类实现

public class Singleton {
    private Singleton() {
    }

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

    public static Singleton getUniqueInstance() {
        return SingletonHolder.INSTANCE;
    }
}

Ⅵ 枚举实现

工厂模式:

  1. 简单工厂(Simple Factory)
  • 在创建一个对象时不向客户暴露内部细节,并提供一个创建对象的通用接口。
  • 简单工厂把实例化的操作单独放到一个类中,这个类就成为简单工厂类,让简单工厂类来决定应该用哪个具体子类来实例化。
  1. 工厂方法(Factory Method)
  • 定义了一个创建对象的接口,但由子类决定要实例化哪个类。工厂方法把实例化操作推迟到子类。
  • 在简单工厂中,创建对象的是另一个类,而在工厂方法中,是由子类来创建对象。
  1. 抽象工厂(Abstract Factory)
  • 提供一个接口,用于创建相关的对象家族 。
  • 抽象工厂模式创建的是对象家族,也就是很多对象而不是一个对象,并且这些对象是相关的,也就是说必须一起创建出来。而工厂方法模式只是用于创建一个对象,这和抽象工厂模式有很大不同。从高层次来看,抽象工厂使用了组合,即 Cilent 组合了 AbstractFactory,而工厂方法模式使用了继承。

观察者模式:

  • 定义对象之间的一对多依赖,当一个对象状态改变时,它的所有依赖都会收到通知并且自动更新状态。
  • 主题(Subject)是被观察的对象,而其所有依赖者(Observer)称为观察者。
  • 主题(Subject)具有注册和移除观察者、并通知所有观察者的功能,主题是通过维护一张观察者列表来实现这些操作的。
  • 观察者(Observer)的注册功能需要调用主题的 registerObserver() 方法。
主题:
public interface Subject {
    void register(Observer o);

    void remove(Observer o);

    void notify();
}

public class WeatherData implements Subject {
    private List<Observer> observers;
    private float temperature;

    public WeatherData() {
        observers = new ArrayList<>();
    }

    public void set(float temperature) {
        this.temperature = temperature;
        notify();
    }

    @Override
    public void register(Observer o) {
        observers.add(o);
    }

    @Override
    public void remove(Observer o) {
        observers.remove(o);
    }

    @Override
    public void notify() {
        for (Observer o : observers) {
            o.update(temperature);
        }
    }
}
观察者:
public interface Observer {
    void update(float temp);
}

public class Observer1 implements Observer {
    public Observer1 (Subject weatherData) {
        weatherData.register(this);
    }

    @Override
    public void update(float temp) {
        System.out.println(temp);
    }
}
  • 静态代理类:由程序员创建或者由第三方工具生成,再进行编译;在程序运行之前,代理类的.class文件已经存在了。静态代理类通常只代理一个类。静态代理事先知道要代理的是什么。
  • jdk动态代理(反射)
  • CGLIB动态代理
    动态代理对比
  1. JDK动态代理是实现了被代理对象的接口,Cglib是继承了被代理对象。
  2. JDK和Cglib都是在运行期生成字节码,JDK是直接写Class字节码,Cglib使用ASM框架写Class字节码,Cglib代理实现更复杂,生成代理类比JDK效率低。
  3. JDK调用代理方法,是通过反射机制调用,Cglib是通过FastClass机制直接调用方法,Cglib执行效率更高。