小小及

设计模式-前言

设计框架、设计原则、设计模式   简介

一、软件模块划分总原则——高聚合低耦合

内聚是从功能角度来度量模块内的联系,一个好的内聚模块应当恰好做一件事。它描述的是模块内的功能联系;

 耦合是软件结构中各模块之间相互连接的一种度量,耦合强弱取决于模块间接口的复杂程度、进入或访问一个模块的点以及通过接口的数据

    高内聚低耦合,是软件工程中的概念,是判断设计好坏的标准,主要是面向对象的设计,主要是看类的内聚性是否高,耦合度是否低。

    内聚就是一个模块内各个元素彼此结合的紧密程度,高内聚就是一个模块内各个元素彼此结合的紧密程度高。

    所谓高内聚是指一个软件模块是由相关性很强的代码组成,只负责一项任务,也就是常说的单一责任原则。

    耦合:一个软件结构内不同模块之间互连程度的度量(耦合性也叫块间联系。指软件系统结构中各模块间相互联系紧密程度的一种度量。模块之间联系越紧密,其耦合性就越强,模块的独立性则越差,模块间耦合的高低取决于模块间接口的复杂性,调用的方式以及传递的信息。) 对于低耦合,粗浅的理解是:

    一个完整的系统,模块与模块之间,尽可能的使其独立存在。

    也就是说,让每个模块,尽可能的独立完成某个特定的子功能。

    模块与模块之间的接口,尽量的少而简单。

    如果某两个模块间的关系比较复杂的话,最好首先考虑进一步的模块划分。

    这样有利于修改和组合。

二、设计框架

可复用面向对象软件系统一般划分为两大类:应用程序工具箱和框架(Framework),我们平时开发的具体软件都是应用程序,Java的API属于工具箱;而框架是构成一类特定软件可复用设计的一组相互协作的类,EJB(EnterpriseJavaBeans)是Java应用于企业计算的框架。

框架通常定义了应用体系的整体结构类和对象的关系等等设计参数,以便于具体应用实现者能集中精力于应用本身的特定细节。框架主要记录软件应用中共同的设计决策,框架强调设计复用,因此框架设计中必然要使用设计模式。

另外,设计模式有助于对框架结构的理解,成熟的框架通常使用了多种设计模式,如果你熟悉这些设计模式,毫无疑问,你将迅速掌握框架的结构,我们一般开发者如果突然接触EJBSpring等框架,会觉得特别难学、难掌握,那么转而先掌握设计模式,无疑是给了你剖析EJB或J2EE系统的一把利器

又例如,桌面程序的框架:MFC、WTL、winform、QT,等;web框架:thinkphp(php web开发框架)、flask(python web开发框架)和Django(python web开发框架)等。

三、设计原则

为什么要提倡“Design Pattern呢?根本原因是为了代码复用,增加可维护性。那么怎么才能实现代码复用呢?面向对象有几个原则:单一职责原则 (Single Responsiblity Principle SRP)开闭原则(Open Closed Principle,OCP)、里氏代换原则(Liskov Substitution Principle,LSP)、依赖倒转原则(Dependency Inversion Principle,DIP)、接口隔离原则(Interface Segregation Principle,ISP)、合成/聚合复用原则(Composite/Aggregate Reuse Principle,CARP)、最小知识原则(Principle of Least Knowledge,PLK,也叫迪米特法则)。开闭原则具有理想主义的色彩,它是面向对象设计的终极目标。其他几条,则可以看做是开闭原则的实现方法。

设计模式就是实现了这些原则,从而达到了代码复用、增加可维护性的目的。

1.开闭原则

此原则是由Bertrand Meyer提出的。原文是:“Software entities should be open for extension,but closed for modification”。就是说模块应对扩展开放,而对修改关闭。模块应尽量在不修改原(是“原”,指原来的代码)代码的情况下进行扩展。那么怎么扩展呢?我们看工厂模式“factory pattern”:假设中关村有一个卖盗版盘和毛片的小子,我们给他设计一“光盘销售管理软件”。我们应该先设计一“光盘”接口。如图:

[pre]

______________

|<>|

| 光盘 |

|_____________|

|+卖() |

| |

|_____________|

[/pre]

而盗版盘和毛片是其子类。小子通过“DiscFactory”来管理这些光盘。代码为:

1

2

3

4

5

6

public class DiscFactory{

public static 光盘

getDisc(Stringname){

        return(光盘)Class.forName(name).newInstance();

    }

}

有人要买盗版盘,怎么实现呢?

1

2

3

4

5

6

public class 小子{

public static void main(String[] args){

光盘 d = DiscFactory.getDisc("盗版盘");

d.卖();

}

}

如果有一天,这小子良心发现了,开始卖正版软件。没关系,我们只要再创建一个“光盘”的子类“正版软件”就可以了,不需要修改原结构和代码。怎么样?对扩展开放,对修改关闭——“开闭原则”。

工厂模式是对具体产品进行扩展,有的项目可能需要更多的扩展性,要对这个“工厂”也进行扩展,那就成了“抽象工厂模式”。

2.里氏代换原则

里氏代换原则是由Barbara Liskov提出的。如果调用的是父类的话,那么换成子类也完全可以运行。比如:

1

2

光盘 d = new 盗版盘();

d.卖();

要将“盗版盘”类改为“毛片”类,没问题,完全可以运行。Java编译程序会检查程序是否符合里氏代换原则。还记得java继承的一个原则吗?子类override方法的访问权限不能小于父类对应方法的访问权限。比如“光盘”中的方法“卖”访问权限是“public”,那么“盗版盘”和“毛片”中的“卖”方法就不能是protected或private,编译不能通过。为什么要这样呢?你想啊:如果“盗版盘”的“卖”方法是private。那么下面这段代码就不能执行了:

1

2

光盘 d = new 盗版盘();

d.卖();

可以说:里氏代换原则是继承复用的一个基础。

3.依赖倒转原则

指在软件里面,把父类都替换成它的子类,程序的行为没有变化。简单的说,子类型能够替换掉它们的父类型。依赖性倒转其实可以说是面向对象设计的标志,用哪种语言编程并不是很重要。

4.接口隔离原则

定制服务的例子,每一个接口应该是一种角色,不多不少,不干不该干的事,该干的事都要干

5.合成/聚合复用

合成/聚合复用原则(Composite/Aggregate Reuse Principle,CARP)经常又叫做合成复用原则。合成/聚合复用原则就是在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分;新的对象通过向这些对象的委派达到复用已有功能的目的。它的设计原则是:要尽量使用合成/聚合,尽量不要使用继承。

就是说要少用继承,多用合成关系来实现。我曾经这样写过程序:有几个类要与数据库打交道,就写了一个数据库操作的类,然后别的跟数据库打交道的类都继承这个。结果后来,我修改了数据库操作类的一个方法,各个类都需要改动。“牵一发而动全身”!面向对象是要把波动限制在尽量小的范围。

在Java中,应尽量针对Interface编程,而非实现类。这样,更换子类不会影响调用它方法的代码。要让各个类尽可能少的跟别人联系,“不要与陌生人说话”。这样,城门失火,才不至于殃及池鱼。扩展性和维护性才能提高。

6.最少知识原则

也叫迪米特法则。不要和陌生人说话,即一个对象应对其他对象有尽可能少的了解。

四、设计模式

基本设计模式有GoF 23种,主要分为创建型模式、结构性模式和行为模式,结构图如下:

 

创建类模式

  • 工厂方法模式,定义一个用于创建对象的接口,让子类决定实例化哪一类,使一个类的实例化 延迟到其子类;
  • 建造者模式,将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示;
  • 抽象工厂模式,为创建一组相关或相互依赖的对象提供一个接口,而且无须指定它们的具体类。
  • 单例模式,确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例;
  • 原型模式,通过对象复制来实现的模式就叫做原型模式,用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

结构类模式

  • 适配器模式,将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作;
  • 桥梁模式,将抽象与实现解耦,使得两者可以独立地变化;
  • 组合模式,将对象组合成树形结构以表示“部分-整体”的场次结构,使得用户对单个对象和组合对象的使用具有一致性。
  • 装饰模式,动态地给一个对象添加一些额外的职责。就增加功能来说 ,装饰模式相比生成子类更为灵活;
  • 门面模式,要求一个子系统的外部与其内部通信必须通过一个统一的对象进行。门面模式提供一个高层次的接口,使得子系统更易于使用。
  • 享元模式,是池技术的重要实现方式,使得共享对象可有效地支持大量的细粒度的对象。
  • 代理模式,为其他对象提供一种代理以控制对这个对象的访问。

行为类模式

  • 责任链模式,使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止;
  • 命令模式,这是一个高内聚的模式,将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能;
  • 解释器模式,是一种按照规定语法进行解析的方案;定义为:给定一门语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示业解释语言中的句子。
  • 迭代器模式,它提供一种方法访问一个容器对象中各个对象,而又不需暴露该对象的内部细节。(目前已经没落);
  • 中介者模式,用一个中介对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
  • 备忘录模式,在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将对象恢复到原先保存的状态。通俗地讲,备忘录模式就是一个对象的备份模式,提供了一种程序数据的备份方法;
  • 观察者模式,也叫做发布订阅模式,定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。
  • 状态模式,状态模式的核心是封装,状态的变更引起了行为的变更。当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了其类。
  • 策略模式,定义一组算法,将每个算法封装起来,并且使它们之间可以互换;
  • 模板方法模式,定义一个操作中的算法的框架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些框架;
  • 访问者模式,封装一些作用于某种数据结构中的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。

posted on 2018-08-02 08:55  小小及  阅读(368)  评论(0编辑  收藏  举报

导航