第三章、优秀的软件架构与如何正确使用设计模式

开始学习设计模式前,我们先来看看软件架构的设计过程,及需要达成的目标和尽量避免的陷阱。

代码复用

无论是开发哪种软件产品,成本和时间都是最重要的。较少的开发时间意味着可以比竞争对手更早进入市场。较低的开发成本意味着能够留出更多的营销资金,覆盖更广泛的潜在客户。

其中,代码复用是减少开发成本最常用的方式之一,其目的非常明显,即:与其反复从头开发,不如在新对象中重用已有的代码。

这个想法表面看起来很棒,但实际上要让已有的代码在全新的代码中工作,还是需要付出额外努力的。组件间紧密的耦合、对具体类而非接口的依赖和硬编码的行为都会降低代码的灵活性,使得复用这些代码变得更加困难。

使用设计模式是增加软件组件灵活性并使其易于复用的方式之一。但是,这可能也会让组件变得更加复杂。

一般情况下,复用可以分为三个层次。在最底层,可以复用类、类库、容器,也许还有一些类的“团体(例如容器和迭代器)”。

框架位于最高层。它们能帮助你精简自己的设计,可以明确解决问题所需的抽象概念,然后用类来表示这些概念并定义其关系。例如,JUnit 是一个小型框架,也是框架的“Hello, world”,其中定义了 Test、TestCase 和 TestSuite 这几个类及其关系。框架通常比单个类的颗粒度要大。你可以通过在某处构建子类来与框架建立联系。这些子类信奉“别给我们打电话,我们会给你打电话的。”

还有一个中间层次。这是我觉得设计模式所处的位置。设计模式比框架更小且更抽象。它们实际上是对一组类的关系及其互动方式的描述。当你从类转向模式,并最终到达框架的过程中,复用程度会不断增加。

中间层次的优点在于模式提供的复用方式要比框架的风险小。创建框架是一项投入重大且风险很高的工作,模式则能让你独立于具体代码来复用设计思想和理念。

扩展性

需求变化是程序员生命中唯一不变的事情。比如以下几种场景:

  • 你在 Windows 平台上发布了一款游戏,现在人们想要 Mac OS 的版本。
  • 你创建了一个使用方形按钮的 GUI 框架,但几个月后开始流行原型按钮。
  • 你设计了一款优秀的电子商务网站,但仅仅几个月后,客户就要求新增电话订单的功能。


每个软件开发者都经历过许多相似的故事,导致它们发生的原因也不少。

首先,在完成了第一版的程序后,我们就应该做好了从头开始优化重写代码的准备,因为现在你已经能在很多方面更好的理解问题了,同时在专业水平上也有所提高,所以之前的代码现在看上去可能会显得很糟糕。

其次,可能是在你掌控之外的某些事情发生了变化,这也是导致许多开发团队转变最初想法的原因。比如,每位在网络应用中使用 Flash 的开发者都必须重新开发或移植代码,因为不断地有浏览器停止对 Flash 格式地支持。

最后,可能是需求的改变,之前你的客户对当前版本的程序感到满意,但是现在希望对程序进行 11 个“小小”的改动,使其可完成原始计划阶段中完全没有提到的功能,新增或改变功能。

当然这也有好的一面,如果有人要求你对程序进行修改,至少说明还有人关心它。因此在设计程序架构时,有经验的开发者都会尽量选择支持未来任何可能变更的方式。

如何正确使用设计模式?

设计模式不是为每个人准备的,而是基于业务来选择设计模式,需要时就能想到它。要明白一点,技术永远为业务服务,技术只是满足业务需要的一个工具。我们需要掌握每种设计模式的应用场景、特征、优缺点,以及每种设计模式的关联关系,这样就能够很好地满足日常业务的需要。

许多设计模式的功能类似,界限不是特别清楚(为了能让大家更好的理解,每个章节后面都列出了类似功能设计模式之间的对比)。大家不要疑惑,设计模式不是为了特定场景而生的,而是为了让大家可以更好和更快地开发。

设计模式只是实现了七大设计原则的具体方式,套用太多设计模式只会陷入模式套路陷阱,最后代码写的凌乱不堪。

在实际工作中很少会规定必须使用哪种设计模式,这样只会限制别人。不能为了使用设计模式而去做架构,而是有了做架构的需求后,发现它符合某一类设计模式的结构,在将两者结合。

设计模式要活学活用,不要生搬硬套。想要游刃有余地使用设计模式,需要打下牢固的程序设计语言基础、夯实自己的编程思想、积累大量的时间经验、提高开发能力。目的都是让程序低耦合,高复用,高内聚,易扩展,易维护。

1. 需求驱动

不仅仅是功能性需求,需求驱动还包括性能和运行时的需求,如软件的可维护性和可复用性等方面。设计模式是针对软件设计的,而软件设计是针对需求的,一定不要为了使用设计模式而使用设计模式,否则可能会使设计变得复杂,使软件难以调试和维护。

2. 分析成功的模式应用项目

对现有的应用实例进行分析是一个很好的学习途径,应当注意学习已有的项目,而不仅是学习设计模式如何实现,更重要的是注意在什么场合使用设计模式。

3. 充分了解所使用的开发平台

设计模式大部分都是针对面向对象的软件设计,因此在理论上适合任何面向对象的语言,但随着技术的发展和编程环境的改善,设计模式的实现方式会有很大的差别。在一些平台下,某些设计模式是自然实现的。

不仅指编程语言,平台还包括平台引入的技术。例如,Java EE 引入了反射机制和依赖注入,这些技术的使用使设计模式的实现方式产生了改变。

4. 在编程中领悟模式

软件开发是一项实践工作,最直接的方法就是编程。没有从来不下棋却熟悉定式的围棋高手,也没有不会编程就能成为架构设计师的先例。掌握设计模式是水到渠成的事情,除了理论只是和实践积累,可能会“渐悟”或者“顿悟”。

5.避免设计过度

设计模式解决的是设计不足的问题,但同时也要避免设计过度。一定要牢记简洁原则,要知道设计模式是为了使设计简单,而不是更复杂。如果引入设计模式使得设计变得复杂,只能说我们把简单问题复杂化了,问题本身不需要设计模式。

这里需要把握的是需求变化的程度,一定要区分需求的稳定部分和可变部分。一个软件必然有稳定部分,这个部分就是核心业务逻辑。如果核心业务逻辑发生变化,软件就没有存在的必要,核心业务逻辑是我们需要固化的。对于可变的部分,需要判断可能发生变化的程度来确定设计策略和设计风险。要知道,设计过度与设计不足同样对项目有害。

学习设计模式,死记硬背是没用的,还要从实践中理解,本教程后面会结合实例和源码来讲解如何使用设计模式。

需要特别声明的是,在日常应用中,设计模式从来都不是单个设计模式独立使用的。在实际应用中,通常多个设计模式混合使用,你中有我,我中有你。下图完整地描述了设计模式之间的混用关系,希望对大家有所帮助。
 

设计模式之间的关系

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值