关于23种设计模式的理解
今天来全面复习一下软件设计模式的相关知识,通过复习这些过去学过的知识,来更好的理解我们要学的软件架构方面的知识。
首先我们先了解一下模式这个词吧,模式最早起源于建筑业,它的定义包含三个方面:Context(模式适用的前提条件)、Problem(在特定条件下需要解决的目标问题)、Solution(对目标问题各种关系的描述)。最后总结出的定义:模式是在特定环境中解决问题的一种方案。模式描述了解决问题的核心,通过这种方式,我们无需再做同样的工作,只需根据模式去复用他们,就可以完成相应的任务。
那么软件设计模式又是什么呢?软件设计模式被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结,使用软件设计模式是为了可重用代码、让代码更容易被他人理解、保证代码的可靠性。而我们根据其目的又可以将软件分为:创建型、结构型和行为型三种。
那么我们首先看一下创建型的各种设计模式。
简单工厂模式
我们可以看到简单工厂模式是创建了一个抽象的产品类,然后你需要具体创建什么产品,只需要在静态的工厂方法类中传递正确的参数,我们工厂类就能根据相应的参数创造出正确的产品,采用简单工厂方法的模式,我们不必再判断出要创建什么类型的产品后,写一大堆的代码,而是只要new出相应的产品即可,降低了系统的耦合性,使工厂方法和产品方法的修改都变得更加容易。
工厂方法模式
我们可以看到工厂方法模式是对简单工厂方法模式的一种完善,在简单工厂方法模式中,如果有新的产品需要加入系统中时,就必须要编写相应的逻辑方法,而这违背了设计模式中的“开闭原则”,而工厂方法模式正解决了这一问题,它将工厂类抽象出来,当需要创建产品时,去交给他的子工厂类去创建,这样当需要创建新产品时,只需要创建一个新的产品类和子工厂类就好,满足了开闭原则。
抽象工厂模式
抽象工厂模式是为了处理工厂所需要生产的产品并不是一个简单的对象,而是处理生产多个位于不同产品等级结构中属于不同类型的具体产品。比如生产电视机和空调,而电视机和空调又可以分为Hair和TCL的,相同品牌的电器被称为产品族,相同类型的电器为产品等级结构,他必须把不同品牌的电器,创造出不同的工厂来创建相应的产品。
建造者模式
在我们的现实生活中,我们经常要建造一个复杂的对象,类似于汽车,我们客户并不关心其中有什么组件和他们的装配细节,而关心的一辆完整的汽车,而在我们的软件中有时也有一些复杂的对象,我们不需要知道里面构建的细节,只需要返回一个完整的对象即可,这时就需要建造者模式。
原型模式
原形模式就是根据一个对象,来复制出多个与原来对象一模一样的对象,其中根据其成员对象是否也克隆分为深克隆和浅克隆。
单例模式
单例模式是为了确保某一个类中只有一个实例,并且这个类会自行实例化这个实例,并且向整个系统提供这个实例。单例模式用处挺大的,像j2ee中那些连接数据库的操作,非常占用内存,如果经常开启新的实例来连接的话,那么系统会吃不消,这时候单例模式就是一个不错的选择了。
接下来是结构型的设计模式,结构型设计模式关注的是通过关联关系使得一个类中去定义另一个类的实例对象
适配器模式
适配器就像我们的电脑充电器,可以通过它使我们的电脑充上电。适配器模式可以理解为通过一个接口使接口不兼容的那些类可以同时工作,比如我们可以通过一个转化接口使机器人类可以模仿人的行为。
桥接模式
就是使抽象和实现分开,使他们可以各自独立的发生变化,比如画笔的大小和颜色,如果我们简单的将他们组合去一个个实例化,那就太复杂了,如果采用桥接模式的话,我们只需将抽象类中的相应的实现取出来就好了。
组合模式
组合模式就是将多个对象以树形结构表示出来,其中容器对象类和容器之间有一个聚合关联关系,通过这个关联,可以使容器对象包含叶子,也可以包含容器对象,以此实现递归组合,形成一个树形结构。典型的代表就是文件夹和文件的关系。
装饰模式
装饰模式,就如其名字,其目的就是为了动态的给一个对象增加一些额外的职责,就像给一个照片加上不同类型的相框一样,装饰模式是在一个已有的构件类上进行相应的装饰,比如变形金刚的例子,刚开始是一辆汽车,进行装饰之后可以变成机器人。
外观模式
外观模式,就像网站的首页一样,一个网站包含许多子模块,如果一个用户每次想进入相应的子模块,都要自己输入相应子模块的地址,那就太麻烦了,而首页就很好的解决了这一问题,用户只需记住一个首页的网址,然后在进行选择就好了。这就是外观模式,通过一组接口来为子系统提供一个一致性的界面,这个接口使子系统更加容易使用。
享元模式
享元模式是一个为了提高系统的性能的设计模式,在系统运行的过程中,有许多对象都是类似的,他们在被应用的时候状态很小,因此我们可以建立一个享元类保存这个重用率很高的类,当用户需要时首先从享元类中检查一下有没有所需要的类,如果有的话,就不需要重新创建了,就是通过这样的方法来提高系统的效率。
代理模式
代理模式,类似于我们买房时候的房屋代理,有的时候我们不能我们想要访问的对象(如房主)进行直接的沟通,这时候我们就需要一个代理,代理模式就是解决这样问题的一个模式,像spring中AOP就是典型的代理模式,代理模式,使我们通过代理间接的访问一个对象,对其进行操作。
最后是行为模式的内容,行为模式不仅关注类和对象的结构,重点关注他们之间的相互作用。
职责链模式
职责链模式的目的主要是避免请求发送者与接收者耦合在一起,让多个对象都有可能接收到请求,将这些对象链成一条链,并沿着这条链传递请求。职责链模式由每一个对象对其下家的引用连成一条链。例如我们的请假条,首先交给辅导员处理,辅导员处理不了,交给系主任处理,系主任处理不了交给院长,就是这么一层层的形成一条链。
命令模式
命令模式主要是解决那种我们需要向系统中的某些对象发送请求,但却不知道请求的接收者具体是谁,也不知道被请求的操作具体是哪个,我们只需在程序具体运行时指定具体的请求接收者即可。比如电视遥控器的操作,我们并不知道,具体执行开机、关机、换频道的具体对象是哪个,但是我们只需用遥控器发送相关的命令即可。
解释器模式
如果在系统中某一特定类型的问题发生的频率很高,此时可以考虑将这些问题实例表述成为一个语言中的句子,因此可以构成一个解释器,改解释器通过这些句子来解释这些问题。这一模式主要应用于面向对象语言开发的编译器中。
迭代器模式
迭代器模式主要是提供一种方法来访问聚合对象,而不用暴露这个对象的内部表示。比如像java中的集合类,我们就可以通过迭代器模式进行遍历,但又不需要去了解其内部结构。
中介者模式
通过一个对象来封装一系列的对象交互,中介者使用对象不需要显示地相互引用,可以降低耦合性,使他们可以独立的改变他们之间的交互。这个模式就像我们的qq群一样,有了qq群,我们想和多个人聊天,就不用一个个的和他们进行聊天,只要通过群就可以实现多人同时进行聊天。
备忘录模式
备忘录模式,我们对软件进行操作的时候,难免会犯一些错误,这时我们就需要利用我们的备忘录模式来保存每一次系统操作的状态,一旦我们进行错误的操作,我们把之前的状态取出就可以回到以前的状态。
观察者模式
观察者模式,定义了对象之间的一种一对多依赖关系,它使得当每一个对象状态发生改变时,其相关依赖对象皆得到通知并且自动更新。他的原理就像股票和股民一样,当股票上涨时,股民就会兴奋;当股票下跌时,股民就会伤心失望。
状态模式
很多情况下,一个对象的行为取决于一个或者多个动态变化的属性,这样的属性就叫做状态,而往往当对象的状态改变时,他的行为也会发生相应的变化,如当一个人开心时,他就可能唱歌、请客吃饭;伤心时,就可能自己一个人默默的悲伤,这就是状态的改变引起行为上的变化,而状态模式正是用来描述这样行为的模式。
策略模式
在多数情况下,我们实现某个目标的途径不止一条,例如人们外出旅行的出行方式。我们可以根据自己能承受的经济限度,选择不同的出行方法。而策略模式正是将解决问题的不同方法封装起来,使他们可以相互替换,而具体选择哪个就需要根据实际情况具体而定了。
模板方法模式
在生活中,我们可能都经历过这种情况,比如请客吃饭,我们都会经历点菜,吃东西和买单几个步骤,而到底吃什么则由用户自己决定。模板方法模式就是描述这样一种情况的模式,它先将算法的骨架写出来,而将一些用户要决定的事情推迟到子类中决定。
访问者模式
访问者模式,表示一个作用于某对象结构中的各元素的操作,它是我们可以在不改变各元素的类的前提下定义作用于这些元素的新操作。比如对于购物车中的水果和图书,收银员的操作是计算价格,进行收款,而顾客的操作则是进行付款。