菜鸟笔记
提升您的技术认知

23种设计模式

5分钟学习23种设计模式

阿里巴巴开发手册

七大设计原则

1.单一职责原则(Single responsibility):单个接口或类不应该有多个职责,应该尽可能的划分职责,通过组合的方式,完成更为复杂的业务

2.接口隔离原则(Interface Segregation):一个接口不要包含过多的职责,应合理划分,跟单一职责原则相辅相成

典型场景:动物、人、鸟,人和鸟都会吃,人会走路,鸟会飞,应该把走路和飞这两个行为抽象成接口,通过组合的方式让人拥有走路的行为,让鸟拥有飞的行为。再细划分,人有多个走路姿势,鸟有多个飞行方式,可以分别继承走路和飞的抽象行为扩展其具体的行为

3.依赖倒转原则(Dependence Inversion):高层模块不应该依赖于底层模块,二者都应该依赖其抽象,依赖倒置的中心思想是面向接口编程

4.里氏替换原则(Liskov Substitution):

一.在使用继承时,遵循里氏替换原则,在子类中尽量不要重写父类的方法。

二.继承实际上让两个类耦合性增强了,给程序带来侵入性。在适当的情况下,可以通过聚合,组合,依赖来解决问题。

三.继承包含这样一层含义:父类中凡是已经实现好的方法,实际上是在设定规范和契约,虽然它不强制要求所有的子类必须遵循这些契约,但是如果子类对这些已经实现的方法任意修改,就会对整个继承体系造成破坏。

5.开闭原则 OCP(Open Closed):

一.开闭原则(Open Closed Principle) 是编程中最基础、最重要的设计原则。

二.一个软件实体,比如类,模块和函数应该对提供方扩展开放,对使用方修改关闭。用抽象构建框架,用实现扩展细节。

三.当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。

四.编程中遵循其它原则,以及使用设计模式的目的就是遵循开闭原则。

6.迪米特法则(Demeter):

一.一个对象应该对其他对象保持最少的了解(最少知道原则 LKP)。

二.类与类关系越密切,耦合度越大。要求降低类之间耦合,而不是完全解耦。

三.迪米特法则(Demeter Principle),即一个类对自己依赖的类知道的越少越好。也就是说,对于被依赖的类不管多么复杂,都尽量将逻辑封装在类的内部。对外除了提供public方法,不对外泄露任何信息。

四.迪米特法则更简单的定义:只与直接的朋友通信。

五.直接的朋友:每个对象都会与其他对象有耦合关系,只要两个对象之间有耦合关系,我们就说这两个对象之间是朋友关系。耦合的方式很多,依赖,关联,组合,聚合 等。其中,我们称出现成员变量,方法参数,方法返回值中的类为直接的朋友,而出现在局部变量中的类不是直接的朋友。也就是说,陌生的类最好不要以局部变量的形式出现在类的内部。

7.合成复用原则(Composite Reuse):

一.合成复用原则 尽量使用组合/聚合的方式,而不是使用继承。

二.找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。

三.针对接口编程,而不是针对实现编程。

四.为了交互对象之间的松耦合设计而努力。

设计模式类型

创建型模式:
    单例模式(Singleton Pattern)
    抽象工厂模式(Abstract Factory Pattern)
    原型模式(Prototype Pattern)
    建造者模式(Builder Pattern)
    工厂模式(Factory Pattern)

结构型模式:
    适配器模式(Adapter Pattern)
    桥接模式(Bridge Pattern)
    装饰器模式(Decorator Pattern)
    组合模式(Composite Pattern)
    外观模式(Facade Pattern)
    享元模式(Flyweight Pattern)
    代理模式(Proxy Pattern)

行为型模式:
    模板模式(Template Pattern)
    命令模式(Command Pattern)
    访问者模式(Visitor Pattern)
    迭代器模式(Iterator Pattern)
    观察者模式(Observer Pattern)
    中介者模式(Mediator Pattern)
    备忘录模式(Memento Pattern)
    解释器模式(Interpreter Pattern)
    状态模式(State Pattern)
    策略模式(Strategy Pattern)
    责任链模式(Chain of Responsibility Pattern)

1.单例模式

确保一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。那么就要求它的构造方法一定不能是public公开的,即不能被外界进行实例化,那它的构造方法只能是private,并且是用static修饰的。单例模式的最佳实践是无状态的。

2.简单工厂模式

又称为静态工厂方法模式,它属于类创建型模式。在简单工厂模式中,可以根据参数的不同返回不同类的实例。简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。


优点:实现对象的创建和使用分离,创建完全交给专门的工厂类负责,开发人员只需要关心怎么使用就行。
缺点:简单工厂类不够灵活,如果新增一个产品就休要修改工厂类,违反了开闭原则,无法做到灵活的扩展。

3.工厂模式

从之前的核心工厂变成了一个抽象接口,它负责给出工厂应该实现的方法,它不再负责所有产品的创建而是将具体产品的创建工作交给子类去做,这样就诞生了具体的子工厂即子类,负责生成具体的产品对象。可以将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定应该实例化哪一个具体实例类。因此,工厂模式中新增一个产品不需要修改原有的工厂类,但是需要新增一个工厂。开闭原则规定,程序对扩展是开放的,对修改是封闭的。
JDK中Collection使用了工厂模式
Collection是一个接口,定义了一个方法

用于生产Iterator对象即迭代器对象,实现集合接口的有很多实现类,比如ArrayList,它也可以生产适合ArrayList的迭代器对象

4.抽象工厂模式

工厂模式生产的是一大类产品,抽象工厂可以生产具体某一大类产品,还可以生产其他大类产品,打破了工厂与产品(大类)一对一的关系

5.装饰器模式

动态的给一个对象添加一些额外的功能。就增加的功能来说,装饰器模式比生产子类更加灵活。


在使用的使用通过将new生成的对象传给装饰器就可以了。
Java的IO流大量的使用了装饰器模式。

6.适配器模式

将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够一起工作。

7.观察者模式

观察者模式也称为发布-订阅模式,定义对象间的一种一对多的依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。

8.外观模式

要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行。外观模式提供一个高层次的接口,使得子系统更易使用。缺点则是不符合开闭原则,如果子系统要扩展的话,必须要修改外观模式的类。

9.状态模式

允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。其别名为状态对象(Objects for States),状态模式是一种对象行为模型。



HandsomeForum开发时经常使用卫语句优化if-else

10.策略模式

定义一组算法,将每个算法都封装起来,并且使它们之间可以互换。策略模式让算法独立于使用它的客户而变化,也称为政策模式(Policy)。

线程池的四种拒绝策略就使用了策略模式。

11.代理模式

为其他对象提供一种代理以控制对这个对象的访问。

12.责任链模式

责任链模式(Chain of Responsilibity)是一种处理请求的模式,它让多个处理器都有机会处理改请求,直到其中某个处理成功为止。责任链模式把多个处理器串成链,然后让请求在链上传递。

缺点:每个请求需要从链头走到链尾,当链条比较长的时候,性能会大幅下降,其次,它不利于调试,它采取递归的方式,调试的时候比较复杂。

13.模板方法模式

定义一个操作中的算法的框架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤。符合开闭原则。

14.享元模式

运用共享技术有效地支持大量细粒度的对象。享元模式最典型的应用就是池技术,字符串常量池,数据库连接池,线程池等。


优点:相同的对象在内存中只保留一份,节约系统资源,提高系统性能。
缺点:分离出内外状态,逻辑变复杂。

15.命令模式

命令模式是一种行为设计模式,它可将请求转换为一个包含与请求相关的所有信息的独立对象。该转换让你能根据不同的请求将方法参数化、延迟请求执行或将其放入队列中,且能实现可撤销操作。

16.建造者模式

建造者模式又称为生成器模式,它是一种创建型设计模式,它可以使得我们分步骤创建复杂对象。

17.原型模式

实现Cloneable接口。在java语言有一个Cloneable接口,它的作用只有一个,就是在运行时通知虚拟机可以安全地在实现了此接口的类上使用clone方法。在java虚拟机中,只有实现了这个接口的类才可以被拷贝,否则在运行时会抛出CloneNotSupportedException异常。
重写Object类中的clone方法。Java中,所有类的父类都是Object类,Object类中有一个clone方法,作用是返回对象的一个拷贝,但是其作用域protected类型的,一般的类无法调用,因此,Prototype类需要将clone方法的作用域修改为public类型。
原型模式是一种比较简单的模式,也非常容易理解,实现一个接口,重写一个方法即完成了原型模式。在实际应用中,原型模式很少单独出现。经常与其他模式混用,他的原型类Prototype也常用抽象类来替代。

class Prototype implements Cloneable {
  
    public Prototype clone(){
  
        Prototype prototype = null;
        try{
  
            prototype = (Prototype)super.clone();
        }catch(CloneNotSupportedException e){
  
            e.printStackTrace();
        }
        return prototype; 
    }
}
class ConcretePrototype extends Prototype{
  
    public void show(){
  
        System.out.println("原型模式实现类");
    }
}
public class Client {
  
    public static void main(String[] args){
  
        ConcretePrototype cp = new ConcretePrototype();
        for(int i=0; i< 10; i++){
  
            ConcretePrototype clonecp = (ConcretePrototype)cp.clone();
            clonecp.show();
        }
    }
}

18.备忘录模式

备忘录模式是一种行为设计模式,允许在不暴露对象实现细节的情况下保存和恢复对象之前的状态。

19.迭代器模式

迭代器模式是一种行为设计模式,让你能在不暴露集合底层表现形式(列表、栈和树等)的情况下遍历集合中所有的元素。

20.组合模式

组合模式是一种结构型设计模式,你可以使用它将对象组合成树状结构,并且能像使用独立对象一样使用它们。

21.桥接模式

桥接模式将继承关系转换为关联关系,从而降低类与类之间的耦合,减少了代码的编写量。

优点:分离抽象接口及其实现部分,提高系统灵活度。它通过关联方式而不是继承方式,可以减少系统类的个数。
缺点:需要较高的抽象能力,会增加系统的理解与设计难度。

22.中介者模式

优点:简化了对象之间的交互,将各参与者进行解耦,对于复杂的对象之间的交互,引入中介者,可以简化各类的设计和实现。
缺点:具体中介者包含了参与者的交互细节,会使中介者类本身非常复杂并且难以维护。

23.访问者模式

优点:符合开闭原则,不需要对类进行扩展就可以增加新的功能也满足单一职责,新的指令完全交给访问器去定义。
缺点:访问者需要定义很多访问元素,新增一个元素,接口就要添加一个方法,如果定义很多访问者就需要全部改造。