除了封装,继承,多态 您还知道那些?-面向对象设计的金字塔

引言

面向对象设计原则你知道吗?熟悉吗?除了封装,继承,多态你还了解多少OOD 原则?

确认自己已是OOD精通的“大侠”请绕路。

不知道,也别急,且听我细细道来。

关键词和定义都提供双语,让我们感受下原汁原味,顺便学点专业英语…

 

基本的面向对象原则(Basic OO principles)

作为专科出生程序员,上学的时候我们第一次接触面向对象编程(OOP)的语言时就会提及这三个最基本原则

  1. Encapsulation(封装)
  2. Inheritance(继承)
  3. Polymorphism(多态)

当然还也还有与之相关的一些原则 abstraction(抽象), association(关联), aggregation(聚合), and composition(组合)

 

这种原则就像 ABC 书,因为它们定义了面向对象世界的基础。

这些东西虽然听起来很熟悉,但您是否真正理解了,还需要晒晒你的代码啦…(事实是检验一切唯一的依据)

这知识就不再这里赘述啦,大家可自行google,百度,也可翻翻大学那些已经尘封已久的教科书,说不定还会捡起一些其他的回忆,微笑

熟悉的SOLID(‘类’层次设计原则)

面向对象设计原则科学界定最常见派生方法构建健壮且灵活的系统。

而SOLID原则又被证明是解决无法被基本的面向对象原则捕获的众多 OO 设计问题的最佳工具。 该不该掌握自己掂量,大笑

缩写 全称 中文名称 相关论文链接
SRP Single Responsibility Principle 单一责任原则 The Single Responsibility Principle
OCP Open / Closed Principle 开放封闭原则 The Open Closed Principle
LSP Liskov Substitution Principle 里氏替换原则 The Liskov Substitution Principle
ISP Interface Segregation Principle 接口分离原则 The Interface Segregation Principle
DIP Dependency Inversion Principle 依赖倒置原则 The Dependency Inversion Principle

单一责任原则

There should never be more than one reason for a class to change。

翻译:类修改的原因应(理由或者动机)该只有一个。

 

开放封闭原则

Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.

翻译:软件实体(类、模块、函数等)应该是可以扩展的,但是不可修改的。

 

里氏替换原则

Subtypes must be substitutable for their base types.

翻译:子类型(subtype)必须能够替换掉它们的基类型(base type)

 

依赖倒置原则

High level modules should not depend upon low level modules. Both should depend upon abstractions.

Abstractions should not depend upon details. Details should depend upon abstractions。

翻译:

A、 高层模块不应该依赖于低层模块,两者都应该依赖于抽象。

B、  抽象不应该依赖于细节,细节应该依赖于抽象。 

 

接口分离原则

Clients should not be forced to depend upon methods that they do not use. Interfaces belong to clients, not to hierarchies.

翻译:应该强迫客户依赖于它们不要的方法。接口属于客户,不属于它所在的类层次结构。

 

 

包的设计原则

      随着应用程序的规模和复杂度的增加,需要在更高的层次对它们进行组织。类对于小型应用程序来说事非常方便的组织单元,但是对于大型应用程序来 说,如果仅仅使用类作为唯一的组织单元,就会显得粒度过细。因此,就需要比类“大”的“东西”来辅助大型应用程序的组织。这个“东西”就是包 (package)。

      本节描述了6个原则。前3个原则关注包的内聚性,这些原则能够指导我们如何把类划分到包中。后3个原则关注包的耦合性,这些原则帮助我们确定包之间的相互关系。

 

包的内聚性原则(粒度)

  • Reuse-Release Equivalence Principle (REP) 重用-发布等价原则
  • Common-Reuse Principle(CCP) 共同重用原则。
  • Common-Closure Principle(CRP)共同封闭原则。

这3个关于包的内聚性原则,可以帮助开发者决定如何把类划分到包中

这些原则依赖于这样的事实:至少已经存在一些类,并且它们之间的相互关系也已经确定。

因此,这些原则是根据“自底向上”的观点对类进行划分的。

包的耦合性原则(稳定性)

  • Acyclic-Dependency Principle(ADP) 无环依赖原则 。
  • Stable-Dependency Principle (SDP) 稳定依赖原则。
  • Stable-Abstractions Principle (SAP) 稳定抽象原则。

这3个包的耦合性原则,用来处理包之间的关系

这里,我们会再次碰到可开发性与逻辑设计之间的冲突力(tension)。

来自技术和行政方面的作用力都会影响到包的组织结构,并且这种作用力还是易变的。

 

1、The Release Reuse Equivalency Principle (REP):重用发布等价原则

      The granule of reuse is the granule of release.

      翻译: 重用粒度等价于发布粒度。

2、The Common Reuse Principle (CRP):共同重用原则

     The classes in a package are reused together. If you reuse one of the classes in a package, you reuse them all. 
     翻译:包的所有类被一起重用。如果你重用了其中的一个类,就重用全部。

3、The Common Closure Principle (CCP):共同封闭原则

     The classes in a package should be closed together against the same kinds of changes. a change that affects a package affects all the classes in that package. 
     翻译:一个包中所有的类应该对同一种类型的变化关闭。一个变化影响一个包,便影响了包中所有的类。

------------------------------------------------------------------------------------------------

1、Acyclic-Dependency Principle(ADP) 无环依赖原则

The dependency structure between packages must be a directed acyclic graph (DAG). That is, there must be no cycles in the dependency structure. 
     翻译:包之间的依赖结构必须是一个直接的无环图形(DAG)。也就是说,在依赖结构中不允许出现环(循环依赖)。

2、Stable Dependencies Principle (SDP):稳定依赖原则

    The dependencies between packages in a design should be in the direction of the stability of the packages. A package should only depend upon packages that are more stable that it is.
    翻译:一个设计中的包之间的依赖应该朝着稳定的方向进行。一个包只应该依赖那些比自己更稳定的包。

3、Stable Abstractions Principle (SAP):稳定抽象等价原则

    Packages that are maximally stable should be maximally abstract. Instable packages should be concrete. The abstraction of a package should be in proportion to its stability. 
    翻译:最稳定的包应该是最抽象的包。不稳定的包应该是具体的包。包的抽象程度跟它的稳定性成正比。

设计模式

GOF的23种经典模式,还有后面有 23 种基本的设计模式由"四人帮 "Gang of Four (Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides), 以及martin Fowler 51 企业应用架构模式65 企业集成模式。还有很多特定于特定问题域模式。

这里就经典23中模式做下简单回顾,其他的模式请自行Google 百度,也可以查看我提供的参考资料。

创建

结构

行为

---------------------------------------创建----------------------------------------------------------------------------

 

工厂方法(Factory Method pattern)

【学习难度:★★☆☆☆,使用频率:★★★★★

Define an interface for creating an object,but let subclass decide which class to instantiate.Factory Method lets a class defer instantiation to subclass.

翻译:定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法是一个类的实例化延迟到其子类。

 

抽象工厂(Abstact Factory)

【学习难度:★★★★☆,使用频率:★★★★★

Provide an interface for creating families of related or dependent objects without specifying their concrete classes.

翻译:为创建一组相关或相互依赖的对象提供一个接口,而且无需指定它们的具体类。

 

单例模式(Singleton pattern)

【学习难度:★☆☆☆☆,使用频率:★★★★☆

Ensure a class has only one instance,and provide a global point of access to it.

翻译:确保一个类只有一个实例,并提供一个全局访问点来访问这个唯一实例。

 

建造者(Builder Pattern)

【学习难度:★★★★☆,使用频率:★★☆☆☆

Separate the construction of a complex object form its representation so that the same construction process can create different representations.

翻译:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

 

原型模式(Prototype Pattern)

【学习难度:★★★☆☆,使用频率:★★★☆☆

Specify the kinds of objects to create using a prototypical instance,and create new objects by copying this prototype.

翻译:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

 

 

补充一个不属于23经典模式的常用模式:

简单工厂模式(Simplified version of Factory Method)

【学习难度:★★☆☆☆,使用频率:★★★☆☆

Creates objects without exposing the instantiation logic to the client and Refers to the newly created object through a common interface.

翻译:简单工厂模式创建对象不暴露具体初始化对象的逻辑(一般通过一个表示具体类输入参数,又工厂自行创建对象),且客户端是引用的新创建对象的接口(或者基类而不不是具体的子类)。

简单工厂模式的实质是由一个工厂类根据传入的参数动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例。

-------------------------------------------------------------------------------------------------------------------

适配器模式(Adapter Pattern)

【学习难度:★★☆☆☆,使用频率:★★★★☆

Convert the inface of a class into another interface clients expect.Adapter lets classes work together that couldn't otherwise because of incompatible interface.

翻译:将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。

“系统的数据和行为都正确,单接口不符时,我们应该考虑使用适配器,目的是是控制范围之外的一个原有对象与某个接口匹配。适配器模式主要用于希望复用一些现存的类,但是接口又与复用环境不一致的情况。”(《大话设计模式》)

 

桥接模式(Bridge Pattern)

【学习难度:★★★☆☆,使用频率:★★★☆☆

Decouple an abstraction from its implementation so that the two can vary independently.

翻译:将抽象和实现解耦,使得两者可以独立的变化。

 

组合模式(Composite Pattern)

【学习难度:★★★☆☆,使用频率:★★★★☆

Compose objects into tree structure to represent part-whole hierarchies.Composite lets clients treat individual objects and compositions of objects uniformly.

翻译:将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。

 

装饰模式(Decorator Pattern)

【学习难度:★★★☆☆,使用频率:★★★☆☆

Attach additional responsibilities to an object dynamically keeping the same interface.Decorators provide a flexible alternative to subclassing for extending functionality.

翻译:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。

 

外观模式(Facade Pattern)

【学习难度:★☆☆☆☆,使用频率:★★★★★

Provide a unified interface to a set of interface in a subsystem.Facede defines a higher-level interface that makes the subsystem easier to use.

翻译:要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行。门面模式提供了一个高层次的接口,使得子系统更容易使用。

 

享元模式(Flyweight Pattern)

【学习难度:★★★★☆,使用频率:★☆☆☆☆

Use sharing to support large numbers of fine-grained objects efficiently.

翻译:使用共享对象可有效地支持大量的细粒度对象。

 

代理模式(Proxy pattern)

【学习难度:★★★☆☆,使用频率:★★★★☆

Provide a surrogate (代理) or placeholder for another object to control access to it.

翻译:为其他对象提供一种代理以控制对这个对象的访问。

  

-------------------------------------------------------------------------------------------------------------------

  

职责链模式(Chain of Responsibility Pattern)

学习难度:★★★☆☆,使用频率:★★☆☆☆

Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request.Chain the receiving objects and pass the request along the chain until an object handles it.

翻译:使多个对象有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系 。将这些对象连成一个链,并沿着这条链传递请求,知道有对象处理它为止。

 

命令模式(Command Pattern)

【学习难度:★★★☆☆,使用频率:★★★★☆

Encapsulate a request as an object,thereby letting you parameterize clients with different requests,queue or log requests, and support undoable operations.

翻译:将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。

 

解释器模式(Interpreter Pattern)

【学习难度:★★★★★,使用频率:★☆☆☆☆

Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences int the language.

翻译:给定一门语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。

 

迭代器模式(Iterator Pattern)

【学习难度:★★★☆☆,使用频率:★★★★★

Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.

翻译:它提供一种方法访问一个容器对象中各个元素,而又不需要暴露该对象的内部细节。

 

中介者模式(Mediator Pattern)

【学习难度:★★★☆☆,使用频率:★★☆☆☆

Define an object that encapsulates how a set of objects interact.

Mediator promotes loose couping by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently.

翻译:用一个中介对象封装一系列的对象交互,中介者使各对象不需要显示的相互作用,从而使其耦合松散,而且可以独立的改变它们之间的交互。

 

备忘录模式(Memento Pattern)

【学习难度:★★☆☆☆,使用频率:★★☆☆☆

Without violating encapsulation, capture and externalize an object's internal state so that the object can be restored to this state later.

翻译:在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样以后就可将该对象恢复到原来保存的状态。

 

观察者模式(Observer Pattern)

【学习难度:★★★☆☆,使用频率:★★★★★

Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

翻译:定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。

 

状态模式(State Pattern)

【学习难度:★★★☆☆,使用频率:★★★☆☆

Allow an object to alter its behavior when its internal state changes.The object will appear to change its class.

翻译:当一个对象在状态改变时允许其改变行为,这个对象看起来像改变了其类。

 

策略模式(Strategy Pattern)

【学习难度:★☆☆☆☆,使用频率:★★★★☆

Define a family of algorithms, encapsulate each one, and make them interchangeable.

翻译:定义一组算法,将每个算法都封装起来,并且使他们之间可以互换。

 

模板方法模式(Template Method Pattern)

【学习难度:★★☆☆☆,使用频率:★★★☆☆

Define the skeleton of an algorithm in an operation,deferring some steps to subclasses.

Template Method lets subclass redefine certain steps of an algorithm without changing the algorithm's structure.

翻译:定义一个操作中的算法框架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可以重定义该算法的某些特定步骤。

 

访问者模式(Visitor Pattern)

【学习难度:★★★★☆,使用频率:★☆☆☆☆

Represent an operation to be performed on the elements of an object structure.Visitor lets you define a new operation without changing the classes of the elements on which it operates.

翻译:封装一些作用于某种数据结构中的各种元素,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。

 

在大多数情况下,有可能想出相应的设计模式为解决特殊问题。但有些情况,现有设计模式还解决不了或者提供一种低效率的解决方案。在这种情况下,还需要SOLID设计原则。

 

关系

 

上面所介绍的基础的面向对象原则和SOLID+包设计原则以及设计模式之间的关系该怎么表述了?先看下面这张图

Picture1

 

 

从下往上数,第一层和第二层原则之间的关系(面向对象设计原则和基础的面向设计对象之间的关系),看图。

细节太多,就不在该篇幅中展开说了。

fig2

总结

想做打造现代企业级系统 ,你作为面向对象设计师最起码应该具备以下

(a) 应该精通基本的面向对象原则,

(b) 掌握面向对象设计的原则和

(c) 了解设计模式。

此外因为面向对象设计原则集中于不同方面的 OOD,加上其中有些原则有时会有争议地方。所以知道或即使掌握该金字塔中一个或两个OOD原则还远远不足以开发出健壮、 灵活、 可扩展的和稳定的软件。OOD人员和OOP人员必须考虑金字塔中所有级别的设计并系统地应用它们才能真正做好OOD(节省设计时间和提高设计质量)。

 

参考于引用资料

Principles Of Object Oriented Design

Design Principles and Design Patterns - Object Mentor

一些软件设计的原则

package-diagrams.pdf

Three Sources of a Solid Object-Oriented Design

面向对象软件设计原则(三) —— 软件实体的设计原则

面向对象软件设计原则(四) —— 包的设计原则

《C#设计模式》PPT及源码分享

设计模式导学目录(完整版)

How I explained OOD to my wife

Design Patterns

SOLID architecture principles using simple C# examples

 

后记:修改了@foreach_break 提及的错误。

posted @ 2015-07-09 14:28  霍旭东  阅读(3022)  评论(11编辑  收藏  举报