那一年我的学长面试死在了设计模式上 -- 23种设计模式+额外常用设计模式汇总合集(持续更新)
设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。
设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。
毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理地运用设计模式可以完美地解决很多问题,每种模式在现实中都有相应的原理来与之对应,每种模式都描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是设计模式能被广泛应用的原因。
设计模式分为三大类:
创建型模式 (5种):
1. 工厂方法模式 (Factory Pattern)
2. 抽象工厂模式 (Abstract Factory Pattern)
3. 单例模式 (Singleton Pattern)
4. 建造者模式 (Builder Pattern)
5. 原型模式(Prototype Pattern)
结构型模式 (7种):
1. 适配器模式 (Adapter Pattern)
2. 装饰者模式(Decorator Pattern)
3. 代理模式(Proxy Pattern)
4. 外观模式(门面模式Facade Pattern)
5. 桥接模式 (Bridge)
6. 组合模式(Composite Pattern)
7. 享元模式(Flyweight Pattern)
行为型模式(11种):
1. 策略模式 (Strategy Pattern)
2. 模板方法模式(Template Pattern)
3. 观察者模式(Observer Pattern)
4. 迭代子模式(Iterator Pattern)
5. 责任链模式 (Chain of Responsibility Pattern)
6. 命令模式(Command Pattern)
7. 备忘录模式(Memento Pattern)
8. 状态模式(State Pattern)
9. 访问者模式(Visitor Pattern)
10. 中介者模式(Mediator Pattern)
11. 解释器模式(Interpreter Pattern)
不在23种的额外两类:
并发型模式
1. 发布者/订阅者模式
线程池模式
不属于以上,但也经常使用的:
1. 简单工厂模式
2. 工厂模式
设计模式的七大原则:
- 单一职责原则SRP(Single Responsibility Principle)
就一个类而言,应该仅有一个引起它变化的原因。 - 开放-关闭原则OCP(Open-CLosed Principle)
一个软件的实体应该对扩展开放,对修改关闭。 - 里氏代换原则(Liskov Substitution Principle)
子类型必须能够替换他们的基类(父类)。 - 依赖倒置原则DIP(Dependence Inversion Principle)
要依赖于抽象,不要依赖于具体。 - 最少知识原则LKP(Least Knowledge Principle)或称 迪米特法则(LoD)
一个类对于其他类知道的越少越好,就是说一个对象应当对其他对象有尽可能少的了解,只和朋友通信,不和陌生人说话 - 接口隔离原则(ISP)
使用多个专门的接口比使用单一的功能更多的总接口要好 - 合成/聚合原则
要尽量使用合成/聚合,而不是继承关系达到复用的目的
1.单一职责原则SRP(Single Responsibility Principle)
所谓单一职责原则就是一个类仅有一个引起它变化的原因。这里变化的原因就是所说的“职责”。如果一个类有多个引起它变化的原因,那么也就意味着这个类有多个职责,再进一步说,就是把多个职责耦合在一起了。
2.开放-关闭原则OCP(Open-CLosed Principle)
所谓开放-闭合原则,指的是,一个类应该对扩展开放,最修改关闭。一般也被简称开闭原则,开闭原则是设计中非常核心的一个原则。
开闭原则要求的是,类的行为是可以扩展的,而且是在不修改已有代码的情况下进行扩展,也不必改动已有的源代码或者二进制代码。
实现开闭原则的关键就在于合理地抽象、分离出变化和不变化的部分,为变化的部分留下可扩展的方式,比如,钩子方法或者是动态组合对象等。
这个原则看起来也很简单。但事实上,一个系统要全部做到遵守开闭原则,几乎是不可能的,也没这个必要。适度的抽象可以提高系统的灵活性,使其可扩展、可维护,但是过度的抽象,会大大的增加系统的复杂程度。应该在需要改变的地方应用开闭原则就可以了,而不用到处使用,从而陷入过度设计。
3.里氏代换原则(Liskov Substitution Principle)
子类型(subtype)必须能够替换它们的基(父)类型。(子类可以以父类的身份出现)。
比如,如果是父类是鸟,鸟会飞。企鹅🐧不会飞,企鹅是鸟吗?所以企鹅不能继承鸟这个类。
4.依赖倒置原则DIP(Dependence Inversion Principle)
所谓依赖倒置原则,指的是,要依赖于抽象,不要依赖于具体类。要做到依赖倒置,典型的应用应该做到:
- 高层模块不应该依赖于底层模块,二者都应该依赖于抽象
- 抽象不应该依赖于具体实现,具体实现应该依赖于抽象
- 一般高层模块包含对业务功能的处理和业务策略选择,应该被重用的,是高层模块去影响底层的具体实现。
- 要针对接口编程,而不是针对实现编程
因此,这个底层的接口与应该由高层提出的,然后由底层实现的,也就是说底层接口的所有权在高层模块,因此是一种所有权的倒置。
启示:好的程序应该强内聚,松耦合。
5.最少知识原则LKP(Least Knowledge Principle)或称 迪米特法则(LoD)
这个原则用来指导我们在设计系统的时候,应该尽量减少对象之间的交互,对象只和自己的朋友谈话,也就是只和自己的朋友交互,从而松散类之间的耦合。通过松散类之间的耦合来降低类之间的相互依赖,这样在修改系统的某一个部分的时候,就不会影响其他的部分,从而使得系统具有更好的维护性。
那么哪些对象才能当做朋友呢?
- 当前对象本身
- 通过方法的参数传递过来的对象
- 当前对象所创建的对象
- 当前对象的实例变量所引用的对象
- 方法内所创建或者实例化的对象
其根本思想:
- 强调了类之间的松耦合。
- 类之间的耦合越弱,越有利于复用,一个处于弱耦合的类被修改,不会对有关系的类造成波及。
- 信息的隐藏促进了软件的复用。
6.接口隔离原则(ISP)
接口隔离原则(Interface Segregation Principle)讲的是:使用多个专门的接口比使用单一的总接口要好。换而言之,从一个客户类的角度来讲:一个类对另外一个类的依赖性应当是建立在最小接口上的。
过于臃肿的接口是对接口的污染。不提倡使用,也不应该是用Dirt Interface。
7.合成/聚合原则
要尽量使用合成/聚合,而不是继承关系达到复用的目的。
合成/聚合原则就是在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分;新的对象通过向这些对象的委派达到复用已有。
写在最后:
我叫风骨散人,名字的意思是我多想可以不低头的自由生活
,可现实却不是这样。家境贫寒,总得向这个世界低头,所以我一直在奋斗,想改变我的命运
给亲人好的生活,希望同样被生活绑架的你
可以通过自己的努力改变现状,深知成年人的世界里没有容易二字。目前是一名在校大学生,预计考研,热爱编程,热爱技术,喜欢分享,知识无界,希望我的分享可以帮到你!
如果有什么想看的,可以私信我,如果在能力范围内,我会发布相应的博文!
感谢大家的阅读!😘你的点赞、收藏、关注是对我最大的鼓励!
更新:
- 2020年4月21日: 完善一些不在23种内,但也经常使用的设计模式
- 2020年4月22日: 完善简单工厂模式,增加了一些图例
- 2020年4月23日: 补充观察者模式
- 2020年4月24日: 在大佬的提醒下,更新了观察者模式并纠正错误
- 2020年4月25日: 更新发布者/订阅者模式,并分析了与观察者的区别