23种设计模式之综合实战篇
- 1. 设计模式概述
- 1.1 什么是设计模式
- 1.2 设计模式的好处
- 2. 设计原则分类
- 3. 详解
- 3.1 单一职责原则
- 3.2 开闭原则
- 3.3 里氏代换原则
- 3.4 依赖倒转原则
- 3.5 接口隔离原则
- 3.6 合成复用原则
- 3.7 迪米特法则
- 4. Awakening
1. 设计模式概述
我们的软件开发技术也包括一些招式和内功:
Java、C#、C++等编程语言,Eclipse、Visual Studio等开发工具,JSP、ASP.net等开发技术,Struts、Hibernate、JBPM等框架技术,所有这些我们都可以认为是招式。而数据结构、算法、设计模式、重构、软件工程等则为内功。
1.1 什么是设计模式
俗话说:站在别人的肩膀上,我们会看得更远。设计模式的出现可以让我们站在前人的肩膀上,通过一些成熟的设计方案来指导新项目的开发和设计,以便于我们开发出具有更好的灵活性和可扩展性,也更易于复用的软件系统。
设计模式的一般定义如下:
设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的
总结,使用设计模式是为了可重用代码、让代码更容易被他人理解并且保证代码可靠性。
对于面向对象软件系统的设计而言,在支持可维护性的同时,提高系统的可复用性是一个至关重要的问题,如何同时提高一个软件系统的可维护性和可复用性是面向对象设计需要解决的核心问题之一。在面向对象设计中,可维护性的复用是以设计原则为基础的。每一个原则都蕴含一些面向对象设计的思想,可以从不同的角度提升一个软件结构的设计水平。
1.2 设计模式的好处
设计模式至少有如下几个用途:
1.设计模式来源众多专家的经验和智慧,它们是从许多优秀的软件系统中总结出的成功的、能够实现可维护性复用的设计方案,使用这些方案将可以让我们避免做一些重复性的工作。
2.设计模式提供了一套通用的设计词汇和一种通用的形式来方便开发人员之间沟通和交流,使得设计方案更加通俗易懂。
3.大部分设计模式都兼顾了系统的可重用性和可扩展性,这使得我们可以更好地重用一些已有的设计方案、功能模块甚至一个完整的软件系统,避免我们经常做一些重复的设计、编写一些重复的代码。
4.合理使用设计模式并对设计模式的使用情况进行文档化,将有助于别人更快地理解系统。
5.学习设计模式将有助于初学者更加深入地理解面向对象思想,让你知道:如何将代码分散在几个不同的类中?为什么要有“接口”?何谓针对抽象编程?何时不应该使用继承?如果不修改源代码增加新功能…
2. 设计原则分类
设计原则名称 | 描述 | 使用频率 |
---|---|---|
单一职责原则 (Single Responsibility Principle, SRP) | 一个类只负责一个功能领域中的相应职责 | ⭐️⭐️⭐️⭐️ |
开闭原则 (Open-Closed Principle,OCP) | 软件实体应对扩展开放,而对修改关闭 | ⭐️⭐️⭐️⭐️⭐️ |
里氏代换原则 (Liskov Substitution Principle, LSP) | 所有引用基类对象的地方能够透明地使用其子类的对象 | ⭐️⭐️⭐️⭐️⭐️ |
依赖倒转原则 (Dependence Inversion Principle, DIP) | 抽象不应该依赖于细节,细节应该依赖于抽象 | ⭐️⭐️⭐️⭐️⭐️ |
接口隔离原则 (Interface Segregation Principle, ISP) | 使用多个专门的接口,而不使用单一的总接口 | ⭐️⭐️ |
合成复用原则 (Composite Reuse Principle, CRP) | 尽量使用对象组合,而不是继承来达到复用的目的 | ⭐️⭐️⭐️⭐️ |
迪米特法则 (Law of Demeter, LoD) | 一个软件实体应当尽可能少地与其他实体发生相互作用 | ⭐️⭐️⭐️ |
3. 详解
3.1 单一职责原则
- 单一职责原则(Single Responsibility Principle, SRP):一个类只负责一个功能领域中的相应职责
- 单一职责原则告诉我们:一个类不能太“累”!
3.2 开闭原则
- 开闭原则(Open-Closed Principle, OCP):一个软件实体应当对扩展开放,对修改关闭。
- 任何软件都需要面临一个很重要的问题,即它们的需求会随时间的推移而发生变化。当软件系统需要面对新的需求时,我们应该尽量保证系统的设计框架是稳定的。
- 如果我要新增一个char,就要在CharDisplay中做判断
- 现在只要继承AbstractChart即可
3.3 里氏代换原则
- 里氏代换原则(Liskov Substitution Principle, LSP):所有引用基类(父类)的地方必须能透明地使用其子类的对象。
- 在软件中将一个基类对象替换成它的子类对象,程序将不会产生任何错误和异常,反过来则不成立,如果一个软件实体使用的是一个子类对象的话,那么它不一定能够使用基类对象。
3.4 依赖倒转原则
- 依赖倒转原则(Dependency Inversion Principle, DIP):抽象不应该依赖于细节,细节应当依赖于抽象。
- 在程序代码中传递参数时或在关联关系中,尽量引用层次高的抽象层类,即使用接口和抽象类进行变量类型声明、参数类型声明、方法返回类型声明,以及数据类型的转换等,而不要用具体类来做这些事情。
3.5 接口隔离原则
- 接口隔离原则(Interface Segregation Principle, ISP):使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口。
- 当一个接口太大时,我们需要将它分割成一些更细小的接口,使用该接口的客户
端仅需知道与之相关的方法即可。每一个接口应该承担一种相对独立的角色,不干不该干的事,该干的事都要干。
3.6 合成复用原则
- 合成复用原则就是在一个新的对象里通过关联关系(包括组合关系和聚合关系)来使用一些已有的对象,使之成为新对象的一部分;新对象通过委派调用已有对象的方法达到复用功能的目的。
- 在面向对象设计中,可以通过两种方法在不同的环境中复用已有的设计和实现,即通过组合/聚合关系或通过继承,但首先应该考虑使用组合/聚合,组合/聚合可以使系统更加灵活,降低类与类之间的耦合度,一个类的变化对其他类造成的影响相对较少;其次才考虑继承。
- 前期,客户不多的时候,将CustomerDAO作为DBUtil类的子类
- 后面,客户增加,又增加了oracle数据库,
3.7 迪米特法则
- 迪米特法则(Law of Demeter, LoD):一个软件实体应当尽可能少地与其他实体发生相互作用。
- 一个系统如果符合迪米特法则,那么当其中某一个模块发生修改时,就会尽量少地影响其他模块,扩展会相对容易
- 当一个按钮(Button)被单击时,对应的列表框(List)、组合框(ComboBox)、文本框(TextBox)、文本标签(Label)等
- 引入一个专门用于控制界面控件交互的中间类(Mediator)来降低界面控件之间的耦合度。引入中间类之后,界面控件之间不再发生直接引用,而是将请求先转发给中间类,再由中间类来完成对其他控件的调用。
4. Awakening
在一秒钟内看到本质的人和花半辈子也看不清一件事本质的人,自然是不一样的命运。