模式是在特定环境中解决问题的一种方案,不同的领域有不同的模式。随着软件工程领域的发展,模式的一般概念被应用到软件开发领域,软件设计模式被提出,设计模式的出现能让我们以前人一些成熟的设计方案为基础,来指导我们新项目的开发和设计,使用设计模式就是为了可重用代码,让代码更容易被他人理解。
根据使用目的将设计模式分为创建型模式、结构型模式、行为型模式三种类型。
(一)创建型模式
创建型模式关注对象的创建过程,将对象的创建和对象的使用分离,在使用对象时无须知道对象的创建细节。创建型模式包括简单工厂模式、工厂方法模式、抽象工厂模式、建造者模式、原型模式、单例模式。
工厂系列的3个设计模式,主要是针对软件设计中的开闭原则,即程序应该对扩展开放,对修改封闭。我们可以通过维护配置文件的方式,来控制程序的逻辑。简单工厂模式不是23种模式之一。当我们的程序在实例化对象时,如果输入条件不一样,产生的对象也不一样,那么我们可以考虑使用简单工厂对不同的实例进行统一封装。需要什么,只需要传入一个正确的参数,就可以获取所需要的对象,不关心创建细节。由于简单工厂模式只提供了一个工厂类,当有新产品加入到系统中时,必须修改工厂类,加入必要的处理逻辑,违背了“开闭原则”,因此出现工厂方法模式,它的核心是一个抽象工厂类,对于某种类型的对象来说,会有一个特定的对象工厂指向它,这样当我们需要添加一种新类型的产品时,只需要添加两个类,一个是具体产品类,一个是新产品的工厂类,这样更加灵活。由于一个工厂有时候需要的不是一个单一的对象产品,而是多个产品等级结构,就引入了抽象工厂模式。抽象工厂模式是所有形式的工厂模式中最为抽象和最具一般性的一种形态,增加新的具体工厂和产品族很方便,无须修改已有系统,符合“开闭原则”。
对于一些复杂对象来说,它可以分成多个不同的部分,在实例化时,不同部分之间实例化的顺序是一定的,这时我们就可以使用建造者模式了,比如一份套餐需要一步步的装配完成。主要解决在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。
在程序运行过程中,当需要有新的实例对象时,有时并不希望是重新创建一个对象,而是希望新的实例的状态和某个已存在的实例保持一致,此时需要原型模式,一些软件的复制粘贴操作就是原型模式的应用。
单例模式是最简单的设计模式,一个类只有一个实例,必须自行创建这个实例,鼻祖自行向整个系统提供实例,身份证号码具有唯一性,这就是单例模式的一个场景。
(二)结构型模式
结构型模式就像搭积木,简单的积木组合成功能强大的结构,类或者对象结合在一起形成更大的结构。结构型模式包括适配器模式、桥接模式、组合模式、装饰模式、外观模式、享元模式、代理模式。
适配器使原本不兼容的事物一起工作,适配器的存在,就是为了将已存在的东西转换成适合我们的需要、能被我们所利用的东西,使用适配器模式时,客户端一定要针对抽象目标类进行编程,
桥接模式用一种巧妙的方式处理继承存在的问题,用抽象关联取代了传统的多层继承,抽象化与实现化脱耦,它们可以沿着各自的维度独立变化。跨平台视频播放器就是桥接模式的一个场景。
组合模式组合多个对象形成树形结构,可以清楚地定义分层次的复杂对象,增加新的构件更容易。每次使用电脑时所遇到的文件系统,由目录和文件组成。每个目录都可以装内容。目录的内容可以是文件,也可以是目录。按照这种方式,计算机的文件系统就是以递归结构来组织的。这种情况就可以使用组合模式。
装饰模式用于替代继承,关联关系取代继承关系,在不改变一个对象本身的基础上给对象增加额外的新行为,提供了比继承更多的灵活性。可以使用多个具体装饰类来装饰同一对象,得到功能更为强大的对象。
外观模式是一种使用频率非常高的设计模式,引入了一个外观角色来简化客户端与子系统之间的操作,为复杂的子系统调用提供了一个统一的入口。如果没有外观类,那么每个客户类需要和多个子系统之间进行复杂的交互,系统的耦合度将很大,而引入外观类之后,客户类只需要直接与外观类交互,客户类与子系统之间原有的复杂引用关系由外观类来实现,从而降低了系统的耦合度。
享元模式主要用于减少创建对象的数量,以减少内存占用和提高性能。运用共享技术有效支持大量细粒度对象的复用。当一个系统有大量相同或相似的对象时可以使用享元模式。
软件系统中,也有代理,给某一个对象提供一个代理,并由代理对象控制对原对象的引用,这就是代理模式,代理模式协调调用者和被调用者,在一定程度上降低了系统的耦合度。
(三)行为型模式
行为型模式关注系统中对象之间的相互交互,通过行为型模式,可以更加清楚划分类与对象的职责,行为型模式包括职责链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式、访问者模式。
当有多个对象处理同一个请求时,可以使用职责链模式,多个对象连接成一条链,链可以是一条直线、一个环或者一个树形结构,一个对象无须知道是哪一个对象处理请求,接收者和发送者都没有对方的明确信息,客户端负责链的创建即可。
在软件系统中,行为请求者与行为实现者通常是一种紧耦合的关系,但需要对行为进行一些处理时,这种耦合关系就必须解开。命令模式将请求的发送者与接收者解耦,命令模式的关键在于引入了抽象命令接口,且发送者针对抽象命令接口编程,只有实现了抽象命令接口的具体命令才能与接收者相关联。
解释器模式不常使用,提供了评估语言的语法或表达式的方式,它实现了一个表达式接口,该接口解释一个特定的上下文。
迭代器模式使用频率非常高,用于对一个聚合对象进行遍历。迭代器的引入可以将数据的遍历功能从聚合对象中分离出来,聚合对象只负责存储数据,而遍历数据由迭代器来完成。此时增加新的聚合类和迭代器类都很方便,无须修改原有代码,满足“开闭原则”。
中介者模式提供了一种简化复杂交互的解决方案,引入一个中介者,将原本对象之间的两两交互转化为每个对象与中介者之间的交互,降低了原有系统的耦合度,系统更加灵活。
备忘录模式提供了一种对象状态的撤销机制,相当于“后悔药”,使系统恢复到原有历史状态。如果系统需要提供回滚操作时,使用备忘录模式非常合适。例如文本编辑器的撤销操作的实现,数据库中事务操作。
观察者模式用于描述对象之间的依赖关系,一个对象的行为导致依赖于它的其他对象发生反应,实现了表示层和数据逻辑层的分离。
状态模式较为复杂,用于解决系统中复杂对象的状态转换以及不同状态下行为的封装问题。状态模式中,每个状态类中既包含了符合条件时的处理方法,也在不符合条件时指明下一个状态类,然后执行该状态类中的处理函数。
策略模式用于算法的自由切换和扩展,解决的是如何让算法和对象分开来,使得算法可以独立于使用它的客户而变化的问题。
模板方法模式可以将一些复杂流程的实现步骤封装在一系列基本方法中,在模板方法模式中,可以将相同的代码放在父类中,而将不同的方法实现放在不同的子类中。需要一个抽象类,将部分逻辑以具体方法以及具体构造函数的形式实现,然后声明一些抽象方法来让子类实现剩余的逻辑。
访问者模式使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变,访问者对象可以处理元素对象上的操作。
这23种设计模式是针对设计问题的通用解决方案。或许我们现在还没有感受到使用设计模式带来的好处,但在以后的项目中,我们应该停下来思考可以用哪种设计模式,站在一个更高的层次去欣赏软件设计。