参考连接
image.png
1、创建型模式:用来描述 “如何创建对象”,它的主要特点是 “将对象的创建和使用分离”。包括单例、原型、工厂方法、抽象工厂和建造者 5 种模式。
2、结构型模式:用来描述如何将类或对象按照某种布局组成更大的结构。包括代理、适配器、桥接、装饰、外观、享元和组合 7 种模式。
3、行为型模式:用来识别对象之间的常用交流模式以及如何分配职责。包括模板方法、策略、命令、职责链、状态、观察者、中介者、迭代器、访问者、备忘录和解释器 11 种模式。

设计模式的六大原则

1、开闭原则(Open Close Principle)
开闭原则的意思是:对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。简言之,是为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类,后面的具体设计中我们会提到这点。
2、里氏代换原则(Liskov Substitution Principle)
里氏代换原则是面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。LSP 是继承复用的基石,只有当派生类可以替换掉基类,且软件单位的功能不受到影响时,基类才能真正被复用,而派生类也能够在基类的基础上增加新的行为。里氏代换原则是对开闭原则的补充。实现开闭原则的关键步骤就是抽象化,而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。
3、依赖倒转原则(Dependence Inversion Principle)
这个原则是开闭原则的基础,具体内容:针对接口编程,依赖于抽象而不依赖于具体。
4、接口隔离原则(Interface Segregation Principle)
这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。它还有另外一个意思是:降低类之间的耦合度。由此可见,其实设计模式就是从大型软件架构出发、便于升级和维护的软件设计思想,它强调降低依赖,降低耦合。
5、迪米特法则,又称最少知道原则(Demeter Principle)
最少知道原则是指:一个实体应当尽量少地与其他实体之间发生相互作用,使得系统功能模块相对独立。
6、合成复用原则(Composite Reuse Principle)
合成复用原则是指:尽量使用合成/聚合的方式,而不是使用继承。

策略模式(strategy)

开闭原则简单讲就是对扩展开放,对修改关闭。
在了解策略模式前先举个例子:
马上就要到年底了,很多公司的年终奖是根据员工的工资基数和年底绩效情况来发放的。

  • 绩效为A的人年终奖有4倍工资
  • 绩效为B的人年终奖有3倍工资
  • 绩效为C的人年终奖是2倍工资。
  • 绩效为D的人年终奖是1倍工资。

假设财务部要求我们提供一段代码,来方便他们计算员工的年终奖。
假设工资基数为1000.

  1. let calculate1 = function(salary,level) {
  2. if(level === 'A') {
  3. return salary * 4;
  4. } else if(level === 'B') {
  5. return salary * 3;
  6. } else if(level === 'C') {
  7. return salary * 2;
  8. } else if(level === 'D') {
  9. return salary * 1;
  10. }
  11. };
  1. let strategies = {
  2. 'A': salary => salary * 4,
  3. 'B': salary => salary * 3,
  4. 'C': salary => salary * 2,
  5. 'D': salary => salary * 1
  6. };
  7. let calculate3 = function(salary,level) {
  8. return strategies[level](salary);
  9. };

工厂模式

实现方法

  1. 简单工厂模式
  2. 工厂方法模式 (实现子类继承父类,不适用js)
  3. 抽象工厂模式 (给简单工厂再套娃一次)

因为后面两种工厂模式使用较少,这里以简单工厂模式为例。简单工厂模式又叫静态工厂模式,由一个工厂对象决定创建某一种产品对象类的实例。主要用来创建同一类对象。它主要适用于创建的对象数量较少,对象的创建逻辑不复杂时使用。说白了,它就是把你new权限收回,由它来统一实例化

单例模式

单例模式老生常谈了,顾名思义就是一个类只有一个实例。

特点

  1. 确保自己只有一个实例。
  2. 必须自己创建自己的实例。
  3. 必须为其他对象提供唯一的实例。

    优点

  4. 节省内存,提高访问速度

  5. 更加灵活更改类的实例化过程
  6. 避免全局使用的类频繁地创建与销毁
  7. 避免对资源的多重占用(比如写文件操作)

    缺点

  8. 与单一职责原则冲突(一个类应该只关心内部逻辑,而不关心外面怎么样来实例化)

  9. 不适用于变化的对象

ps:单一职责原则就是一个类/接口/方法只负责一项职责或职能

使用场景:

  • 1、要求生产唯一序列号。
  • 2、WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。
  • 3、创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。

注意事项:getInstance() 方法中需要使用同步锁 synchronized (Singleton.class) 防止多线程同时进入造成 instance 被多次实例化。

享元模式

定义

享元模式是以共享的方式高效地支持大量的细粒度对象。通过复用内存中已存在的对象,降低系统创建对象实例的性能消耗。
ps:一般是解决系统性能问题的,所以经常用于底层开发,在项目开发中并不常用

应用实例:

1、JAVA 中的 String,如果有则返回,如果没有则创建一个字符串保存在字符串缓存池里面。 2、数据库的数据池。

总结

享元模式是一个优化重复、缓慢和低效数据共享代码的经典结构化解决方案。

代理模式

定义

简单一句话概括,就是为其他对象提供一种代理以控制对这个对象的访问。
代理模式的目的是为了解耦,当一个对象不适合或者不能直接引用另一个对象时,而代理对象可以在对象之间起到中介的作用。

优点

  1. 能将代理对象与真实对象被调用的目标对象分离
  2. 一定程度上降低耦合度,扩展性好
  3. 保护并增强目标对象

    缺点

  4. 因为多增加一个代理对象,会造成请求处理速度变慢

  5. 会造成系统设计中类的数目的增加
  6. 增加了复杂度

使用场景:按职责来划分,通常有以下使用场景: 1、远程代理。 2、虚拟代理。 3、Copy-on-Write 代理。 4、保护(Protect or Access)代理。 5、Cache代理。 6、防火墙(Firewall)代理。 7、同步化(Synchronization)代理。 8、智能引用(Smart Reference)代理。
注意事项: 1、和适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口。 2、和装饰器模式的区别:装饰器模式为了增强功能,而代理模式是为了加以控制。

观察者模式

定义

观察者模式定义一系列对象之间的一对多关系,当一个对象改变、更新状态时,依赖它的都会收到通知改变或者更新。它又被称为 发布-订阅模式

使用场景

当一个对象的状态发生改变,需要通知到其他对象(各位观察者们),大大了降低了对象与对象之间的耦合度。