讲一讲在工作中用到的面向对象设计模式,供大家参考,之后也会继续更新。
面向对象设计(OOD)的七大原则
在面向对象设计中,首先有这几大原则作为前提,然后在此基础之上有了各类设计模式。
开闭原则
开闭原则(Open-Closed Principle, OCP), 一个软件实体应该对扩展开放,对修改关闭。即软件实体应该在尽量不修改代码的情况下进行扩展。在该原则中,软件实体可以指一个软件模块,一个由多个类组成的局部结构或者一个独立的类。
开闭原则是面向对象的可复用设计的第一块基石,他是最重要的设计原则。为了满足开闭原则,需要对系统进行抽象化设计,抽象是开闭原则的关键。
里式替换原则
Liskov Substitution Principle(LSP),里式替换原则,该原则规定“子类必须能够替换其父类,否则不应当设计为其子类”。换句话说,父类出现的地方,都应该能够由其子类代替。所以子类只能去扩展基类,而不是隐藏或则覆盖基类。
依赖倒置原则
Dependence Iversion Principle(DIP), 它讲的是“设计和实现要依赖于抽象而非实体”。一方面抽象化更符合人的思维习惯;另一方面,根据里式替换原则,可以很容易将抽象替换为扩展后的具体,这样可以很好的支持开闭原则。
这里可以看到,在公司的Spring项目开发中,各个层次间通过Interface
进行依赖,也就是基于此原则。
接口隔离原则
Interface Segration Principle(ISP),“将大的接口打散成多个小的独立的接口”。由于Java类支持实现多个接口,可以很容易的让类具有多种接口的特征,同时每个类可以选择性地只实现目标接口。
单一职责原则
Single Responsibility Principle(SRP),单一职责原则。它讲的是不要存在多于一个导致类变更的原因,是高内聚,低耦合的一个体现。
迪米特法则
Law of Demeter or Least Knowledge Principle(LoD or LKP),“一个对象就尽可能少的了解其它对象”,从而实现松耦合。如果一个类的职责过多,由于多个职责耦合在了一起,任何一个职责的变更都可能引起其它职责的问题,严重影响代码的可维护性和可重用性。
该法则实际上和单一职责原则很类似,强调的高内聚,低耦合。
合成/聚合复用原则
Composite/Aggregate Reuse Principle(CARP/CRP),合成/聚合复用原则。如果新对象的某些功能在别的已经创建好的对象里面已经实现,那么应当尽量使用别的对象提供的功能,使之成为新对象的一部分,而不要在重新创建。新对象可以通过向这些对象的委派达到复用已有功能的效果。简而言之,尽量使用合成/聚合,而非使用继承。
这个原则乍一看和迪米特法则相悖,但我的理解是,可以复用的功能应该是有好的抽象得到,而不是胡乱的复用,这里面其实都是考验工程师功力的地方。
关于静态方法
静态方法实际是无状态且面向方法的设计,适合用作工具类,比如Guava
,而不适合用在对象中。不过在Java8
中已经支持了interface
中的静态方法,也应该是作为实现类需要的工具方法存在。
常用的设计模式
Builder模式
Builder模式非常适用于需要多个构造参数的场景,相比于new
一个对象,然后用一堆setter
去赋值的方式,这种模式的可读性显然要强很多。在我的项目中,需要调用其它系统的Rest服务,在拼接URL时,用这种模式就非常方便。
基类
其中包含了基本的prefix
前缀和params
参数。
实现类
这里定义一个语音查询服务的Builder,实际上在build()
中,根据需求还可以设置一些默认参数,所以才基类中将其定义为虚方法。
使用
是不是很简洁且方便。
策略模式和简单工厂模式
策略模式在各类系统中都很常见,其实现也很简单,定义好interface
即可,不同的策略间应该满足隔离和单一职责原则,相互间独立而不耦合。延续刚才的例子,当一个服务需要根据输入参数的不同,去调用不同的服务时,策略模式就非常合适了。
策略模式类图
定义Interface
定义实现策略
定义工厂
使用
这样的策略之后添加修改策略都会很方便,当然简单工厂方法不满足开闭条件,适用于策略较少的场景。
责任链模式
当需要依次处理一个任务时,可以采用责任链模式,这个模式可实际应用在参数校验,或则流程处理中(比如SpringMVC的9大handler,也就是用类似的模式依次产生作用)
定义基类
定义子类
使用
装饰器模式
装饰器模式主要的作用是为现有的类增加新的功能,其使用和实现和代理模式很像,主要的区别在于控制权的转移,代理模式强调访问必须经由代理,而装饰器模式并无此约定。我们经常用到的Java IO类,便是装饰器模式的实现。
基类
实现类
使用
观察者模式
观察者模式在设计中非常常见,系统层面像Zookeeper,JQuery事件等多是使用的该模式。
主题
观察者
使用