常用设计模式

结构型

7种结构型模式:适配器模式、装饰模式、代理模式、外观模式、桥接模式、组合模式、享元模式

1.适配器模式

==适配器模式是其他6种的鼻祖==

其实就是做兼容,比如需要B,现在只有A,那就将A包装成B就好了,比如插座转换10A与16A互转。

分为三种:类的适配器模式、对象的适配器模式、接口的适配器模式

为什么线程池的submit可以传入runnable的实现,利用了适配器。将runnable的适配成callable处理

public Future<?> submit(Runnable task) {
    if (task == null) throw new NullPointerException();
    RunnableFuture<Void> ftask = newTaskFor(task, null);
    execute(ftask);
    return ftask;
}

protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
    return new FutureTask<T>(runnable, value);
}

public FutureTask(Runnable runnable, V result) {
    this.callable = Executors.callable(runnable, result);
    this.state = NEW;       // ensure visibility of callable
}

public static <T> Callable<T> callable(Runnable task, T result) {
    if (task == null)
        throw new NullPointerException();
    return new RunnableAdapter<T>(task, result);
}

2.装饰器模式

对原类做功能扩展, 动态地给一个对象添加一些额外的职责。重点是调用者主动给目标对象动态新增功能

案例 比如 一个饭馆做炒饭和炒面, 店铺升级后需要动态扩展支持加鸡蛋 或者火腿

那么可以设计成原始对象为主食(炒饭或者炒面),装饰抽象类(配菜),配菜实现类有鸡蛋、火腿,在配菜类中都需要传入主食,然后进行包装。最后返回装饰后的对象如鸡蛋炒饭、鸡蛋火腿鸡蛋炒饭

特点 需要创建主食,也需要创建具体配菜,然后才能得到最后的对象。

3.代理模式

也是对原类做功能扩展,但是关注点是对原功能(方法)的增强,比如实现在某方法执行前后加上日志

和装饰器的区别是

代理模式下 甚至不需要知道被代理或者说被扩展的对象长啥样,直接使用代理对象即可。

而装饰器模式:

需要指定被装饰的对象,然后new 装饰品,传入被装饰的对象(一般是构造函数)。然后得到装饰后的那个对象

典型应用:AOP日志

class A{
    doA(){
    
    }
}

class ProxyA extends A{
    A a;
    ProxyA(A a){
         this.a=a;
    }

    doA(){
        a.doA();
    }
}

3.1.静态代理

利用接口来做,代理类实现同一个接口,然后注入需要代理的子类实现到代理类中,然后对接口中的所有方法进行增强

3.2.动态代理

JDK动态代理

原理和静态代理差不多,只是利用实现InvocationHandler和Proxy.newInstance来实现动态传入子类实现,在动态类中invoke方法里拦截进行增强

CGlib

对于没有接口的方法,通过继承该类,作为一个子类来增强父类的方法

4.外观模式(门面模式)

facade 目的是解耦类之间的关系,比如 CPU、Memory、Disk 三个类,开机都需要启动,需要组合起来调用,采用外观模式就是上面包装一层,在这层中分别调用CPU、Memory、Disk 三个类,而不是让这三个类产生依赖互相调用。

5.享元模式

通过工厂方法提供元数据,比如建造一个森林,需要很多树和草,只需要new一次树,一次草,然后缓存到工厂中,以后每次需要树或者草都直接通过工厂获得,减少对象的重复创建开销

类似的还有俄罗斯方块中的每种类型方块。等等

6.桥接模式

7.组合模式

创建型

1.单例

​ 用来保证某个类是单例存在的,如spring中大量存在。

懒汉式 (写法1) 利用静态对象

public class Singleton {  
    private static Singleton instance;  
    private Singleton (){}  
    public static synchronized Singleton getInstance() {  
        if (instance == null) {  
            instance = new Singleton();  
        }  
        return instance;  
    }  
}

懒汉式 (写法2) 标准DCL+volatile 写法,几乎人手必会,此处略。

饿汉式(利用静态对象)

public class SingletonObj{
    static SingletonObj instance = new SingletonObj();
    private SingletonObj(){}
    public static SingletonObj getInstance(){
        return instance;
    }
}

2.建造者模式(生成器模式)

常见的是将一整个复杂的类或者流程拆解成不同的小模块,比如常见的http类封装,将http请求方案拆解成url、body、httpverb、header、useGzip等不同

部分。最后提供一个方法合并成完整方案的过程。这种思路就是生成器模式

再举个例子:如组装台式机可以拆解为cpu+显卡+内存+电源+主板,最后汇总组成一个整体。

3.抽象工厂模式

简单工厂 就是 通过传入类型来返回对应类型的类

工厂方法, 基于上面传入类型不可控,所以改造成为每个类型创建对应类型的方法,需要哪个类型就调用对应的方法即可,

静态工厂方法,基于上面的将这些创建不同类型的方法改为静态的,省去不必要的实例化

4.工厂方法模式

5.原型模式

行为型模式

1.模板方法模式

通俗讲,就是定义一个抽象类作为父类来实现业务需要的功能,此时会遇到其中有一小部分细节点设计时存在分歧没法做决定,将他提取出来变成抽象方法,交由子类去实现(可以理解为钩子),从而实现一套完整的功能。

RestTemplate

2.观察者模式

[观察者(Observer)模式]: 指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式,它是对象行为型模式

简单说就是服务端A变化,需要通知a和b客户端。实现方式是服务端A提供方法让a和b注册进来,比如说A中用map存下注册进来的a和b。当变化的时候调用a和b中指定的同一个方法。当然a和b中看客官需要,也可以会存下A的信息。

3.策略

4.责任链

责任链是将一个互相独立的一些方法因为业务需要而顺序的排列在一起被调用。利用责任链将这些拆成各自独立的方法,然后通过next指针来将他们依次连接起来,形成chain。这样这些方法可以按照业务自由组合成想要的链来服务。比如request请求 需要先判null、判合法性、判是否必填、判是否超标等。

FilterChain

5.命令

6.状态

7.中介者

8.迭代器

9.访问者

10.备忘录

11.解释器