设计模式概述

1、学习设计模式的目的

(1)应对面试

设计模式是程序员的基本功,因此是面试中常考察的知识点。

(2)写出高质量的代码

学好数据结构与算法目的是写出高效的代码,学好设计模式则是为写出高质量的代码。

(3)提高复杂代码的设计和开发能力

掌握好设计模式才能在开发复杂系统时写出易扩展、易用、易维护的代码。

(4)让读源码、学框架事半功倍

优秀的开源项目、框架、中间件为了代码的扩展性、灵活性、可维护性,类结构和类之间的关系都非常复杂,大量使用设计模式和设计思想,因此掌握好设计模式读源码更加容易。

2、设计模式

经典的设计模式有23种,可以分为创建型、结构型、行为型。

2.1、创建型模式

  创建型设计模式包括:单例模式、工厂模式、建造者模式、原型模式。它主要解决对象的创建问题,封装复杂的创建过程,解耦对象的创建代码和使用代码。

(1)单例模式

  单例模式单例模式用来创建全局唯一的对象。一个类只允许创建一个对象(或者叫实例),那这个类就是一个单例类,这种设计模式就叫作单例模式。单例有几种经典的实现方式,它们分别是:饿汉式、懒汉式、双重检测、静态内部类、枚举。

(2)工厂模式

  工厂模式包括简单工厂、工厂方法、抽象工厂这 3 种细分模式。其中,简单工厂和工厂方法比较常用,抽象工厂的应用场景比较特殊,所以很少用到。

  工厂模式用来创建不同但是相关类型的对象(继承同一父类或者接口的一组子类),由给定的参数来决定创建哪种类型的对象。实际上,如果创建对象的逻辑并不复杂,那直接通过 new 来创建对象就可以了,不需要使用工厂模式。当创建逻辑比较复杂,是一个“大工程”的时候,就考虑使用工厂模式,封装对象的创建过程,将对象的创建和使用相分离。

  当每个对象的创建逻辑都比较简单的时候,推荐使用简单工厂模式,将多个对象的创建逻辑放到一个工厂类中。当每个对象的创建逻辑都比较复杂的时候,为了避免设计一个过于庞大的工厂类,推荐使用工厂方法模式,将创建逻辑拆分得更细,每个对象的创建逻辑独立到各自的工厂类中。

  详细点说,工厂模式的作用有下面 4 个,这也是判断要不要使用工厂模式最本质的参考标准。

  ——封装变化:创建逻辑有可能变化,封装成工厂类之后,创建逻辑的变更对调用者透明。

  ——代码复用:创建代码抽离到独立的工厂类之后可以复用。

  ——隔离复杂性:封装复杂的创建逻辑,调用者无需了解如何创建对象。

  ——控制复杂度:将创建代码抽离出来,让原本的函数或类职责更单一,代码更简洁。

  除此之外,工厂模式有一个非常经典的应用场景:依赖注入框架,比如 Spring IOC,它用来集中创建、组装、管理对象,跟具体业务代码解耦,让开发者聚焦在业务代码的开发上。

(3)建造模式

  建造者模式用来创建复杂对象,可以通过设置不同的可选参数,“定制化”地创建不同的对象。建造者模式的原理和实现比较简单,重点是掌握应用场景,避免过度使用。

  如果一个类中有很多属性,为了避免构造函数的参数列表过长,影响代码的可读性和易用性,我们可以通过构造函数配合 set() 方法来解决。但是,如果存在下面情况中的任意一种,就要考虑使用建造者模式了。

  ——把类的必填属性放到构造函数中,强制创建对象的时候就设置。如果必填的属性有很多,把这些必填属性都放到构造函数中设置,那构造函数就又会出现参数列表很长的问题。如果把必填属性通过 set() 方法设置,那校验这些必填属性是否已经填写的逻辑就无处安放了。

  ——如果类的属性之间有一定的依赖关系或者约束条件,继续使用构造函数配合 set() 方法的设计思路,那这些依赖关系或约束条件的校验逻辑就无处安放了。

  ——如果希望创建不可变对象,也就是说,对象在创建好之后,就不能再修改内部的属性值,要实现这个功能,就不能在类中暴露 set() 方法。构造函数配合 set() 方法来设置属性值的方式就不适用了。

(4)原型模式

  如果对象的创建成本比较大,而同一个类的不同对象之间差别不大(大部分字段都相同),在这种情况下,可以利用对已有对象(原型)进行复制(或者叫拷贝)的方式,来创建新对象,以达到节省创建时间的目的。这种基于原型来创建对象的方式就叫作原型模式。

  原型模式有两种实现方法,深拷贝和浅拷贝。浅拷贝只会复制对象中基本数据类型数据和引用对象的内存地址,不会递归地复制引用对象,以及引用对象的引用对象……而深拷贝得到的是一份完完全全独立的对象。所以,深拷贝比起浅拷贝来说,更加耗时,更加耗内存空间。

2.2、结构型模式

 

 

posted @ 2024-04-10 11:54  jingyi_up  阅读(3)  评论(0编辑  收藏  举报