设计模式概述与设计模式之面向对象设计原则

一.概述

1.为什么要学习设计模式?

    首先,从招式与内功的角度来说,Jaca,C#,C++这些开发语言,Eclipse,Android Studio,IntelliJ IDEA,JSP以及各种框架我们可以认为是招式,而数据结构,算法,设计模式,重构,软件工程等则为内功.招式可以很快学会,但内功的修炼需要很长的时间.要想成为一名高级软件开发工程师,设计模式的学习必不可少.

2.设计模式是什么?

    设计模式是一套被反复使用,多数人知晓的,经过分类编目的,代码设计经验的总结,使用设计模式是为了可重用代码,让代码更容易的被人理解并且保证代码的可靠性.设计模式的熟练运用能够让我们站在巨人的肩膀上编程,通过一些成熟的设计方案来指导新项目的开发和设计,以便于我们开发出具有更好的灵活性和扩展性,他人易于复用的软件系统.

3.设计模式的分类.

    根据他们的用途,设计模式可分为创建型,结构型和行为型三种.
    其中创建型模式主要用于描述如何创建对象.包括以下6种.

    1.单例模式 Singleton Pattern
    2.简单工厂模式 Simple Factory Pattern
    3.工厂方法模式 Factory Method Pattern
    4.抽象工厂模式 Abstract Factory Pattern
    5.原型模式 Prototype Pattern
    6.建造者模式 Builder Pattern

    结构型设计模式主要用于描述如何如何实现类或对象的组合,包括以下7种.

    1.适配器模式 Adapter Pattern
    2.桥接模式 Bridge Pattern
    3.组合模式 Composite Pattern
    4.装饰模式 Decorator Pattern
    5.外观模式 Façade Pattern
    7.代理模式 Proxy Pattern

    行为型模式主要用于描述类和对象怎样交互以及怎样分配职责,包括以下11种.

    1.职责链模式 Chain of Responsibility Pattern
    2.命令模式 Command Pattern
    3.解释器模式 Interpreter Pattern
    4.迭代器模式 Iterator Pattern
    5.中介者模式 Mediator Pattern
    6.备忘录模式 Memento Pattern
    7.观察者模式 Observer Pattern
    8.状态模式 State Pattern
    9.策略模式 Strategy Pattern
    10.模板方法模式 Template Method Pattern
    11.访问者模式 Visitor Pattern

    在此只做简单介绍,后续的文章会一一详细阐述.

4.设计模式的作用?

简单来说,设计模式有以下几个作用:

(1)使用这些成熟的设计模式可以使我们避免做一些重复性的工作,在时间就是金钱的今天,设计模式无疑会为有助于我们提高开发和设计效率,但它不保证一定会提高,高效.

(2)设计模式提供了一套通用的设计词汇和一种通用的形式来方便开发人员之间沟通和交流,使得设计方案更加通俗易懂,节省交流和沟通的时间.

(3).大部分设计模式都兼顾了系统的可重用性和可扩展性,这使得我们可以更好的重用一些已有的设计方案,功能模块甚至一个完整的软件系统,避免做一些重复的设计,编写一些重复的代码,设计模式还可以提高系统的灵活性和可扩展性,修改需求更加得心应手.

(4)合理使用设计模式并对设计模式的使用情况进行文档化,将有助于别人更快的理解系统,另外,对于初学者来说,设计模式将有助于初学者更加深入的理解面向对象思想.

二.面向对象设计原则.

1.综述

在面向对象设计原则中,可维护性复用是以设计模式为基础的,每一个原则都蕴含一些面向对象设计的思想,可以从不同的角度提升一个软件结构的设计水平,面向对象设计原则为支持可维护性复用而诞生,这些原则蕴含在很多设计模式中,它们是从许多设计方案中总结出的指导性原则.

2.面向对象设计原则之单一职责原则

单一职责原则用于控制类的粒度大小,定义是:一个类只负责一个功能领域中的相应职责或者是就一个类而言,应该只有一个引起它变化的原因.

单一职责原则是实现高内聚低耦合的指导方针.需要设计人员发现类的不同职责并将其分离.

3.面向对象设计原则之开闭原则

开闭原则的定义:一个软件实体应当对扩展开放,对修改关闭.即软件实体应尽量在不修改原有代码的情况下进行扩展.

为了满足开发原则,需要对系统进行抽象化设计,抽象化是开闭原则的关键.在Java、C#等编程语言中,可以为系统定义一个相对稳定的抽象层,而将不同的实现行为移至具体的实现层中完成。在很多面向对象编程语言中都提供了接口、抽象类等机制,可以通过它们定义系统的抽象层,再通过具体类来进行扩展。如果需要修改系统 的行为,无须对抽象层进行任何改动,只需要增加新的具体类来实现新的业务功能即可,实现在不修改已有代码的基础上扩展系统的功能,达到开闭原则的要求。

4.面向对象设计原则之里氏代换原则

里氏代换原则的定义可以理解为所有引用基类(父类)的地方必须能透明地使用其子类的对象.

例如有两个类,一个类为BaseClass,另一个是SubClass类,并且SubClass类是BaseClass类的子类,那么一个方法如果可以接受一个BaseClass类型的基类对象base的话,如:method1(base),那么它必然可以接受一个BaseClass类型的子类对象sub,method1(sub)能够正常运行。反过来的代换不成立,如一个方法method2接受BaseClass类型的子类对象sub为参数:method2(sub),那么一般而言不可以有method2(base),除非是重载方法。

通俗一点讲,我们在程序设计中应尽量把父类设计为抽象类或者接口,这样我们可以方便的扩展系统的功能,增加新功能时只需要增加一个新的实现类即可.

5.面向对象设计原则之依赖倒转原则

依赖倒转原则定义如下:抽象不应该依赖于细节,细节应当依赖于抽象。换言之,要针对接口编程,而不是针对实现编程。

依赖倒转原则要求我们在程序代码中传递参数时或在关联关系中,尽量引用层次高的抽象层类,即使用接口和抽象类进行变量类型声明、参数类型声明、方法返回类型声明,以及数据类型的转换等,而不要用具体类来做这些事情。为了确保该原则的应用,一个具体类应当只实现接口或抽象类中声明过的方法,而不要给出多余的方法,否则将无法调用到在子类中增加的新方法。

在实现依赖倒转原则时,我们需要针对抽象层编程,而将具体类的对象通过依赖注入(DependencyInjection, DI)的方式注入到其他对象中,依赖注入是指当一个对象要与其他对象发生依赖关系时,通过抽象来注入所依赖的对象。常用的注入方式有三种,分别是:构造注入,设值注入(Setter注入)和接口注入。构造注入是指通过构造函数来传入具体类的对象,设值注入是指通过Setter方法来传入具体类的对象,而接口注入是指通过在接口中声明的业务方法来传入具体类的对象。这些方法在定义时使用的是抽象类型,在运行时再传入具体类型的对象,由子类对象来覆盖父类对象。

6.面向对象设计原则之接口隔离原则

接口隔离原则的定义:使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口。

根据接口隔离原则,当一个接口太大时,我们需要将它分割成一些更细小的接口,使用该接口的客户端仅需知道与之相关的方法即可。每一个接口应该承担一种相对独立的角色,不干不该干的事,该干的事都要干.

在面向对象编程语言中,实现一个接口就需要实现该接口中定义的所有方法,因此大的总接口使用起来不一定很方便,为了使接口的职责单一,需要将大接口中的方法根据其职责不同分别放在不同的小接口中,以确保每个接口使用起来都较为方便,并都承担某一单一角色。接口应该尽量细化,同时接口中的方法应该尽量少,每个接口中只包含一个客户端(如子模块或业务逻辑类)所需的方法即可,这种机制也称为“定制服务”,即为不同的客户端提供宽窄不同的接口。

7.面向对象设计原则之合成复用原则

定义:尽量使用对象组合,而不是继承来达到复用的目的。

在面向对象设计中,可以通过两种方法在不同的环境中复用已有的设计和实现,即通过组合/聚合关系或通过继承,但首先应该考虑使用组合/聚合,组合/聚合可以使系统更加灵活,降低类与类之间的耦合度,一个类的变化对其他类造成的影响相对较少;其次才考虑继承,在使用继承时,需要严格遵循里氏代换原则,有效使用继承会有助于对问题的理解,降低复杂度,而滥用继承反而会增加系统构建和维护的难度以及系统的复杂度,因此需要慎重使用继承复用。

通过继承来进行复用的主要问题在于继承复用会破坏系统的封装性,因为继承会将基类的实现细节暴露给子类,由于基类的内部细节通常对子类来说是可见的,所以这种复用又称“白箱”复用,如果基类发生改变,那么子类的实现也不得不发生改变;从基类继承而来的实现是静态的,不可能在运行时发生改变,没有足够的灵活性;而且继承只能在有限的环境中使用(如类没有声明为不能被继承)

8.面向对象设计原则之迪米特法则

定义:一个软件实体应当尽可能少地与其他实体发生相互作用。

如果一个系统符合迪米特法则,那么当其中某一个模块发生修改时,就会尽量少地影响其他模块,扩展会相对容易,这是对软件实体之间通信的限制,迪米特法则要求限制软件实体之间通信的宽度和深度。迪米特法则可降低系统的耦合度,使类与类之间保持松散的耦合关系。

迪米特法则要求我们在设计系统时,应该尽量减少对象之间的交互,如果两个对象之间不必彼此直接通信,那么这两个对象就不应当发生任何直接的相互作用,如果其中的一个对象需要调用另一个对象的某一个方法的话,可以通过第三者转发这个调用。简言之,就是通过引入一个合理的第三者来降低现有对象之间的耦合度。

本篇文章只是简单的介绍了设计模式,并未对每一种设计模式深入分析,后续的文章会详细分析和介绍23种设计模式.

不足之处请指正评论,谢谢!

猜你喜欢

转载自blog.csdn.net/liuxu841911548/article/details/72809415