SOLID设计原则与工厂模式

在面向对象设计领域里,SOLID是非常经典的设计原则,可以认为它是道,设计模式是术,只有深刻理解了道,才能用好术。下面简单总结一下SOLID原则: Single Responsibility Principle: 每个类只能有一个被修改的原因Open-Close Principle: 对扩展开发,对修改关闭Liskov's Substitution Principle: 派生类必须能够完全替换基类Liskov's Substitution Principle(LSP)Interface Segregation Principle:客户端不应该被强制依赖他们不需要使用的接口Dependency Inversion Principle: 高层次的模块不应该依赖低层次的模块, 双方都应该依赖抽象。抽象不应该依赖具体细节。细节应该依赖抽象。Dependency Inversion Principle下面以工厂模式为例,说明一下SOLID原则在设计模式里的体现:工厂模式属于创建型模式,主要分三种: 简单工厂模式工厂方法模式抽象工厂模式个人觉得第三种模式使用场景较少且比较鸡肋,主要介绍前两种。先来看下简单工厂模式: public abstract class Operation{ private double value1; private double value2; public double getValue1() { return value1; } public void setValue1(double value1) { this.value1 = value1; } public double getValue2() { return value2; } public void setValue2(double value2) { this.value2 = value2; } protected abstract double getResult();}public class OperationAdd extends Operation { @Override protected double getResult(){ return getValue1() + getValue2(); }}public class OperationMinus extends Operation { @Override protected double getResult(){ return getValue1() - getValue2(); }}public class OperationMul extends Operation { @Override protected double getResult(){ return getValue1() * getValue2(); }}public class OperationFactory{ public static Operation createOperation(String operation){ Operation operation = null; switch(operation){ case "+": operation = new OperationAdd(); break; case "-": operation = new OperationMinus(); break; case "*": operation = new OperationMul(); break; default: throw new UnsupportedOperationException("Unsupported Operation:" + operation); } return operation; }}首先,我们必须令Operation的派生类遵循Liskov's Substitution Principle,才能放心的说,无论我们在工厂中创建出哪种Operation的派生类,都能够利用多态替换其后对Operation的引用。其次,工厂模式返回抽象类,使调用工厂的高层模块依赖Operation这个抽象类而不是其某个具体的派生类,这满足了Dependency Inversion Principle。但是,OperationFactory类中包含了所有Operation派生类的创建,后面如果不断的需要增加新的Operation派生类,就需要不断的修改OperationFactory,这违反了Open-Close Principle,就需要引入工厂方法模式: ...

May 28, 2019 · 1 min · jiezi

敏捷开发是如何被跑偏的

今天聊聊敏捷软件过程。 先说结论:据我观察,至少有60%的团队误用了敏捷软件过程,或者说至少60%的团队在进行伪敏捷开发。 与大家通常的认知是相反的,敏捷过程并不是一个非常容易实践或者实施的过程规范。 通常来讲,没有天上掉馅饼的事儿,所以使用敏捷软件过程带来灵活性收益的同时,一定是要付出相应的代价的。 例如: 如果需要实行结对编程,那么在选择团队成员的时候就需要考虑人员的性格特质,或者增加相应的培训和团建活动;如果需要实行测试驱动开发,则要求团队成员对于自动化测试的技术掌握更加熟练和深入;如果需要进行快速设计,则会对开发人员的设计经验有一定的要求,并同时未来一定要有进行重构的时间安排才可以;等等其它最终,你会发现:如果一个团队没有能力实施传统的软件开发过程的话,则他们多半也无法很好的实施敏捷软件过程…… 敏捷过程实施起来其实还是有一些难度的。有一些团队准备实施循序渐进的策略:针对敏捷过程所要求的一些最佳实践,先上一些比较容易实施的,然后在陆续加入其他。 令人失望的是,这样的做法也会引发一些问题。就拿非常流行的极限编程来讲,极限编程所要求的最佳实践实际上是相互循环依赖的!所以仅仅选择某几项最佳实践来进行实施的话,最终会导致整个系统的崩溃!比如: 极限编程讲究的是快速设计,但是其最终的设计合理性和最优性是由CRC讨论会和后续的重构动作来保证的;极限编程省略了冗长的需求分析文档,代之以即用即抛的“用户故事”;但是为了保证功能的正确性,他会有一个更加严峻的要求:现场客户;极限编程没有专门的测试阶段,那么如何保证产品的质量呢?辅助以三个最佳实践:结对、测试先行和持续集成;重构动作保证了架构的最优化,但是谁来保证重构不会对系统带来负面影响呢?测试先行和持续集成;类似的等等于是,有不少团队在实行了敏捷软件过程之后,仍然停留在(或者说倒退回了)游击队式的野生软件开发过程。 那么如何才能够正确的实施敏捷开发过程呢?我理解,至少需要具备如下的前提,才能够比较顺利的实施敏捷过程: 团队成员对面向对象的开发和设计有相当程度的理解和经验(最起码有想要提高或者学习的需求);团队成员能够熟练的使用自动化测试的框架,并编写自动化测试脚本;团队成员能够熟练的使用持续集成的框架或者产品;团队成员平均沟通能力中上,没有表达能力低下者;至少有一个渠道能和客户(或者有足够话语权的客户代表)进行频繁并流畅的沟通;管理者(包括甲方客户)和开发团队之间有相对比较平等的话语权;管理者(包括甲方客户)能够理解(或者信任)开发团队所提出的一些隐性的工作量(例如重构、编写文档、测试脚本等)所带来的时间成本;上述看似并不太高的门槛,却挡住了60%的软件开发工程师……

April 28, 2019 · 1 min · jiezi

The Principles of OOD 面向对象设计原则

本文首发于 vivo 互联网技术微信公众号 https://mp.weixin.qq.com/s/Q_…作者:Robert C. Martin 翻译:张硕本文由来自美国业界大牛——Robert C. Martin(俗称“Bob大叔) 发布在 butunclebob.com 上,已获得翻译授权。英文原文链接:http://butunclebob.com/Articl…本篇概括性的介绍了OOD的设计原则,后续还有更多文章会详细剖析、吃透面向对象业务设计的原则。什么是面向对象设计?它是怎么一回事?使用它会有什么利弊得失?似乎问出这些问题显得有些愚蠢,特别是在一个几乎每个开发者都会使用某种面向对象语言的时代中。然而在我看来,这些问题即极为重要,因为我们中的大多数使用者并不知道答案,当然也不知道如何发挥面向对象语言的最大价值。在我们这个行业发生的所有变革中,有两场是非常成功的,以至于它们已经渗透到我们的思维中,以至于我们认为它们是理所当然的。那就是"结构化设计编程"(也叫面向过程设计)与"面向对象设计编程"。所有主流的现代编程语言都被这两种编程范式深刻影响。甚至是,我们很难摒弃这两种编程范式去写任何一个程序。我们的主流编程语言中没有“GOTO”,因此似乎是遵守了著名的结构化编程"禁令";我们大多数的主流编程语言是基于类并且不支持使用没有写入任何一个类中的变量、函数(方法),因此他们似乎是遵守了面向对象设计中最明显的特点。用这些语言(主流结构化语言或面向对象语言)写出的程序也许看上去是结构化的或面向对象的,但是外表也可以是虚假的。今天的程序员常常不知道这些语言产生的原因以及其中的基础原则。在另一篇博客中,我会讨论结构化编程的设计原则,而在这篇文章中我想要聊聊面向对象设计原则。在1995年3月,在comp.object上,我写过一篇文章,这篇文章也成为我日后众多OOD设计原则文章中的处女作。你们将会在我的PPP书籍中以及发表了我多篇文章的objectmentor网站上看到这些文章,当然也包括那个广为人知的那篇摘要文章。(译者注:PPP指——“Agile Software Development: Principles, Patterns, and Practice,中文即—敏捷软件开发:原则、模式与实践”)这些原则揭示了OOD依赖管理方面的内涵,而在概念化和建模方面并没有深入涉及。然而这并不代表OO在对问题领域的概念化上很薄弱,也不代表OO在建模能力上很薄弱。我很确定在这两方面上,很多从OO设计原则中获得价值。需要注意的是,这些原则非常关注依赖关系管理。(译者注:此处指宽泛概念的依赖关系管理,如系统与系统之间的依赖,模块与模块之间的依赖,类方法直接的依赖)依赖管理是一个大多数架构师需要面对的问题。每当我们在屏幕上看到一堆乱七八糟的遗留代码时,我们都在经历依赖管理不善的结果。糟糕的依赖关系管理导致代码难以更改、脆弱和不可重用。实际上,在我的PPP书中谈到了几种不同的设计风格,都与依赖管理有关。另一方面,当依赖关系得到很好的管理时,代码仍然是灵活可扩展的、健壮的和可重用的。因此,依赖关系管理的思考,以及这些原则的使用,是软件开发人员设计灵活性系统的基础。以下5个原则是阶级设计原则:SRP单一职责原则 指一个类模块包甚至系统 都应该有单一的原则。OCP开闭原则 你应该能够扩展类的行为,而不需要修改它。如果软件系统想要更容易被改变,其设计就必须允许新增代码来修改,而非修改原来代码。LSP 里氏替换原则简答理解就是 如果想要可替换的组件来构建软件系统,那么这些组件就必须遵守共同一个约定,以便让这些组件可以相互替换。ISP 接口隔离原则使细粒度接口特定于客户端,主要告诫设计师应该在设计中避免不必要的依赖。DIP 依赖倒置原则依赖抽象,而非具体实现。此原则指出高层策略性代码不应该依赖实现的代码,相反,那些底层实现应该依赖于高层策略代码。(译者注:这里的“类”泛指:方法和数据的耦合分组)接下来的六条原则是关于包(译者注:指jar、war,而非package)的。在这个上下文中,包是二进制的可交付文件,比如:jar文件,或者dll,而不是java包或c++命名空间。前三个包原则是关于包内聚的,它们告诉我们在包中放入什么:REP 重用发布等价原则 重用的颗粒就是释放的颗粒。CCP 共同封闭原则 一起更改的类被打包在一起。CRP 共同重用原则 一起使用的类被打包在一起。ADP 无环依赖原则 包的依赖关系图必须没有循环。SDP 稳定依赖原则 依赖于稳定性的方向,特别是(变化更多的)具体的元素应该取决于是否要完全依赖于(更稳定的)抽象成分。SAP 稳定抽象原则 抽象性随稳定性而增加。更多内容敬请关注 vivo互联网技术微信公众号注:转载文章请先与微信号:labs2020 联系。

March 29, 2019 · 1 min · jiezi