参考连接
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.
let calculate1 = function(salary,level) {
if(level === 'A') {
return salary * 4;
} else if(level === 'B') {
return salary * 3;
} else if(level === 'C') {
return salary * 2;
} else if(level === 'D') {
return salary * 1;
}
};
let strategies = {
'A': salary => salary * 4,
'B': salary => salary * 3,
'C': salary => salary * 2,
'D': salary => salary * 1
};
let calculate3 = function(salary,level) {
return strategies[level](salary);
};
工厂模式
实现方法
- 简单工厂模式
- 工厂方法模式 (实现子类继承父类,不适用js)
- 抽象工厂模式 (给简单工厂再套娃一次)
因为后面两种工厂模式使用较少,这里以简单工厂模式为例。简单工厂模式又叫静态工厂模式,由一个工厂对象决定创建某一种产品对象类的实例。主要用来创建同一类对象。它主要适用于创建的对象数量较少,对象的创建逻辑不复杂时使用。说白了,它就是把你new权限收回,由它来统一实例化。
单例模式
特点
- 确保自己只有一个实例。
- 必须自己创建自己的实例。
-
优点
节省内存,提高访问速度
- 更加灵活更改类的实例化过程
- 避免全局使用的类频繁地创建与销毁
-
缺点
与单一职责原则冲突(一个类应该只关心内部逻辑,而不关心外面怎么样来实例化)
- 不适用于变化的对象
ps:单一职责原则就是一个类/接口/方法只负责一项职责或职能
使用场景:
- 1、要求生产唯一序列号。
- 2、WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。
- 3、创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。
注意事项:getInstance() 方法中需要使用同步锁 synchronized (Singleton.class) 防止多线程同时进入造成 instance 被多次实例化。
享元模式
定义
享元模式是以共享的方式高效地支持大量的细粒度对象。通过复用内存中已存在的对象,降低系统创建对象实例的性能消耗。
ps:一般是解决系统性能问题的,所以经常用于底层开发,在项目开发中并不常用。
应用实例:
1、JAVA 中的 String,如果有则返回,如果没有则创建一个字符串保存在字符串缓存池里面。 2、数据库的数据池。
总结
享元模式是一个优化重复、缓慢和低效数据共享代码的经典结构化解决方案。
代理模式
定义
简单一句话概括,就是为其他对象提供一种代理以控制对这个对象的访问。
代理模式的目的是为了解耦,当一个对象不适合或者不能直接引用另一个对象时,而代理对象可以在对象之间起到中介的作用。
优点
使用场景:按职责来划分,通常有以下使用场景: 1、远程代理。 2、虚拟代理。 3、Copy-on-Write 代理。 4、保护(Protect or Access)代理。 5、Cache代理。 6、防火墙(Firewall)代理。 7、同步化(Synchronization)代理。 8、智能引用(Smart Reference)代理。
注意事项: 1、和适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口。 2、和装饰器模式的区别:装饰器模式为了增强功能,而代理模式是为了加以控制。
观察者模式
定义
观察者模式定义一系列对象之间的一对多关系,当一个对象改变、更新状态时,依赖它的都会收到通知改变或者更新。它又被称为 发布-订阅模式。
使用场景
当一个对象的状态发生改变,需要通知到其他对象(各位观察者们),大大了降低了对象与对象之间的耦合度。