从本讲开始,咱们就要开始学习第一章中的第三部分内容,即软件设计原则了。

在软件开发中,为了提高软件系统的可维护性和可复用性,增加软件的可扩展性和灵活性,程序员要尽量根据6条原则来开发程序,从而提高软件开发效率、节约软件开发成本和维护成本。

那么是6条原则呢?看过我前面文章的同学肯定知道,就是下面这6条原则。

  1. 开闭原则
  2. 里氏代换原则
  3. 依赖倒转原则
  4. 接口隔离原则
  5. 迪米法特原则
  6. 合成复用原则

本讲我会为大家介绍第一个软件设计原则,即开闭原则。

概述

什么是开闭原则呢?开闭原则就是对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。简言之,是为了使程序的扩展性好,易于维护和升级。

不妨我就举一个现实生活中的例子来说明一下开闭原则吧!在现实生活中,我们可以经常看到这样的一些效果,咱们的笔记本都会预留有一些USB接口,这样,不管是U盘还是一些什么其他的外接设备,例如鼠标、键盘,我们都可以随插随用了,即实现了一个热插拔的效果,也更加方便我们进行扩展。

有些同学可能就会问了,如果要想达到这样一个效果,那么应该怎么办呢?我们需要使用接口和抽象类。为什么要用接口和抽象类呢?因为抽象灵活性好,适应性广,只要抽象的合理,可以基本保持软件架构的稳定。而软件中易变的细节可以从抽象派生来的实现类来进行扩展,当软件需要发生变化时,只需要根据需求重新派生一个实现类来扩展就可以了。

那么也就是说,我们现在只须去定义一个接口或者抽象类,很显然,它们里面定义了所有子类必须重写的方法,也即定义了一些规范,然后我们再去定义其子类,这样,在后期如果我们要进行程序的扩展,那么我们就不需要再去修改原有的代码,而是直接重新再去定义一个子实现类就可以了。

可能我说了这么多,大家还不是特别理解,没关系,下面我会以搜狗输入法的皮肤为例来向大家介绍开闭原则的一个应用。

案例

这块我是以搜狗输入法的皮肤设计为例来介绍开闭原则的一个应用的。

案例分析

搜狗输入法的皮肤是输入法背景图片、窗口颜色和声音等元素的组合。用户可以根据自己的喜爱更换自己的输入法的皮肤,当然,用户可以用默认的,也可以用其他的皮肤,而且他还可以从网上下载新的皮肤。这些皮肤有共同的特点,可以为其定义一个抽象类(AbstractSkin),大家一定要注意,不管是默认的皮肤还是什么其他的皮肤,我们现在的做法就是向上进行抽取,抽取出一个抽象类或者接口,不过这一块咱们使用的是抽象类,如此一来,每一个具体的皮肤(例如DefaultSkin和MeimeixiaSkin)都将是其子类,这样,用户窗体就可以根据需要选择或者增加新的主题,而不再需要修改原代码了。

这样一路分析下来,我们可以发现该案例是能够满足开闭原则的,所以现在咱们就可以通过该案例来演示一下开闭原则了。当然了,在演示之前,大家得能看懂下面的类图,这也是通过以上分析画出来的。

从以上类图中可以看到,顶层有一个抽象的皮肤类,它下面有两个子类,一个是默认的皮肤类,一个是美美侠皮肤类,它俩都需要去重写父类中的抽象方法。当然了,旁边还有一个搜狗输入法类,由于该类拥有显示皮肤的功能,所以它需要用到皮肤,故你能看到我在这里面进行了一个聚合的操作。

当然了,以上类图中还缺少一个测试类,只不过我没有在以上类图中体现出来罢了。

案例实现

接下来,我们便通过代码来实现一下搜狗输入法皮肤设计这个案例。

要想做到这点,咱们首先得打开咱们的开发工具,这里我使用的开发工具是IDEA,相信大家也都是用的它,然后创建一个maven工程,名字不妨起为design_patterns,以后有关设计模式的代码我们统统都会放在这个工程里面,工程创建好之后,不妨接着在其下创建一个包,例如com.meimeixia.principles,在该包下存放的都是我们编写的有关软件设计原则的代码,至于设计模式的代码,后续我会重新再创建一个包来进行存放。

当然了,软件设计原则有多条,要想讲清楚每一条设计原则,我们还得在com.meimeixia.principles包下分别创建多个子包来存放每一条设计原则所对应案例的代码,例如com.meimeixia.principles.demo1包里面存放的就是开闭原则所对应案例(即搜狗输入法的皮肤设计)的代码。

下面,我们就得根据以上类图来写出对应的代码了。

首先,定义一个抽象皮肤类,例如AbstractSkin。

package com.meimeixia.principles.demo1;/*** 抽象皮肤类* @author liayun* @create 2021-05-27 12:52*/
public abstract class AbstractSkin {// 显示的方法public abstract void display();}

然后,再来定义以上抽象皮肤类的子类,咱们定义的第一个子类是默认皮肤类,即DefaultSkin。

package com.meimeixia.principles.demo1;/*** 默认皮肤类* @author liayun* @create 2021-05-27 12:53*/
public class DefaultSkin extends AbstractSkin {@Overridepublic void display() {System.out.println("默认皮肤");}}

咱们定义的第二个子类是美美侠皮肤类,即MeimeixiaSkin。

package com.meimeixia.principles.demo1;/*** 美美侠皮肤类* @author liayun* @create 2021-05-27 12:55*/
public class MeimeixiaSkin extends AbstractSkin {@Overridepublic void display() {System.out.println("美美侠皮肤");}}

以上三个类定义完毕之后,我们还得定义一个类,从以上类图可知,该类的类名叫SougouInput,此外,我们还知道该类聚合了抽象皮肤类。这样,该类的代码应该是下面这样子的。

package com.meimeixia.principles.demo1;/*** 搜狗输入法* @author liayun* @create 2021-05-27 12:56*/
public class SougouInput {private AbstractSkin skin;public void setSkin(AbstractSkin skin) {this.skin = skin;}public void display() {skin.display();}}

可以看到,我在SougouInput类里面定义了一个AbstractSkin类型的成员变量,这就代表了SougouInput类聚合了抽象皮肤类。此外,由于外界要对AbstractSkin类型的成员变量赋值,所以我们还得提供对应的set方法,当然,这里面我没有提供get方法,只是提供了一个set方法用于赋值。最后,在SougouInput类里面我还提供了一个display方法,该方法是用于展示皮肤的,大家注意了,在该方法里面是调用抽象皮肤类的具体子类的display方法去进行皮肤的一个展示的。

SougouInput类定义完之后,别着急,还有一个类需要我们去定义,它就是咱们的测试类,我们可以给它起名为Client。下面我提供了一个编写好的测试类,以供大家参考。

package com.meimeixia.principles.demo1;/*** @author liayun* @create 2021-05-27 12:57*/
public class Client {public static void main(String[] args) {// 1. 创建搜狗输入法对象SougouInput input = new SougouInput();// 2. 创建皮肤对象// DefaultSkin skin = new DefaultSkin();MeimeixiaSkin skin = new MeimeixiaSkin();// 3. 将皮肤设置到输入法中input.setSkin(skin);// 4. 显示皮肤input.display();}}

相信大家都能看懂以上测试类中编写的代码,我就不再详细赘述了。

测试类定义完毕之后,我们来测试一下,看效果是不是我们所想要的,如下图所示,美美侠皮肤打印出来了,看来效果确实是达到了。

如果现在我们不想用美美侠皮肤了,而是想要用默认皮肤,那么只须稍微修改一下测试类即可,怎么修改想必大家都知道了,我也就不再赘述了。这时,你会发现其他四个类的代码都没有进行任何修改,效果便已经实现了。

后期我们可能面临这样一个需求,就是我们还想再去扩展一种皮肤,例如觉醒年代皮肤,那么你觉得现在以上这个案例有没有满足开闭原则呢?很显然,是满足的,你要知道开闭原则是对扩展开放,对修改关闭的,也就是说我们要进行扩展的话是可以的,但是尽量不要去修改我们之前编写的类的代码。

如果现在还想再去扩展一种觉醒年代皮肤,那么此时我们的做法就很简单了,重新再创建一个类,例如JueXingNianDaiSkin,然后让它去继承抽象皮肤类即可。接下来的事情就好办了,只需要把客户端的代码进行一个修改,让其使用觉醒年代皮肤,一切就都OK了。

至此,开闭原则我就为大家介绍到这。

从零开始学习Java设计模式 | 软件设计原则篇:开闭原则相关推荐

  1. 从零开始学习Java设计模式 | 软件设计原则篇:依赖倒转原则

    在本讲,我将为大家介绍软件设计原则里面的第三个原则,即依赖倒转原则. 概述 什么是依赖倒转原则呢?我们来看一下下面这段描述: 高层模块不应该依赖低层模块,两者都应该依赖其抽象:抽象不应该依赖细节,细节 ...

  2. 从零开始学习Java设计模式 | 软件设计原则篇:里氏代换原则

    在本讲中,我来为大家介绍一下软件设计原则里面的第二个原则,即里氏代换原则. 概述 首先,大家应该知道,里氏代换原则是面向对象设计的基本原则之一.那什么是里氏代换原则呢?里氏代换原则是指任何基类可以出现 ...

  3. 从零开始学习Java设计模式 | 软件设计原则篇:接口隔离原则

    在本讲,我将为大家介绍软件设计原则里面的第四个原则,即接口隔离原则. 概述 接口隔离原则是指客户端不应该被迫依赖于它不使用的方法,一个类对另一个类的依赖应该建立在最小的接口上面. 这句话可能不是很好理 ...

  4. 从零开始学习Java设计模式 | 创建型模式篇:原型模式

    在本讲,我们来学习一下创建型模式里面的第四个设计模式,即原型模式. 概述 原型模式就是指用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型对象相同的新对象. 这段话读起来有点绕,是不是? ...

  5. 从零开始学习Java设计模式 | 创建型模式篇:抽象工厂模式

    在本讲,我们来学习一下创建型模式里面的第三个设计模式,即抽象工厂模式. 前言 前面介绍的工厂方法模式中考虑的是一类产品,如畜牧场只养动物.电视机厂只生产电视机(不生产空调.冰箱等其它的电器).计算机学 ...

  6. 从零开始学习Java设计模式 | 创建型模式篇:建造者模式

    在本讲,我们来学习一下创建型模式里面的最后一个设计模式,即建造者模式. 概述 建造者模式是指将一个复杂对象的构建与表示分离,使得同样的构建过程可以创建不同的表示. 读完这句话之后,我估计很多人都已经懵 ...

  7. 设计模式-软件架构设计七大原则及开闭原则详解

    前言 在日常工作中,我们使用Java语言进行业务开发的时候,或多或少的都会涉及到设计模式,而运用好设计模式对于我而言,又是一个比较大的难题.为了解决.克服这个难题,Remi酱特别开了这个博客来记录自己 ...

  8. Java设计原则之单一职责原则、开闭原则、里氏代换原则

    文章目录 面向对象设计原则概述 单一职责原则 开闭原则 里氏代换原则 面向对象设计原则概述 软件的可维护性(Maintainability)和可复用性(Reusability)是两个非常重要的用于衡量 ...

  9. 设计模式-02.经典设计原则-第一节-单一职责原则,开闭原则,里式替换,接口隔离【万字长文系列】

    文章目录 设计模式经典设计原则-第一节 单一职责原则(SRP) 如何理解单一职责原则? 如何判断类的职责是否足够单一? 类的职责是否设计得越单一越好? 开闭原则(OCP) 如何理解"对扩展开 ...

最新文章

  1. [Tesseract]Tesseract 在 Visual Studio 2012 中的配置及调用
  2. bfs广度优先搜索算法_图的广度优先搜索(BFS)
  3. 可遇不可求的Question之不支持一个STA 线程上针对多个句柄的WaitAll
  4. ubuntu在 hdfs上创建一个文件夹_NAS上如何创建和使用加密文件夹?
  5. mysql下载的解压包怎么用_教你安装Mysql(解压版/非安装包)图文教程
  6. 移动应用广告盈利-KeyMob移动广告聚合平台
  7. Android——SMS接收发短信与运行权限
  8. Java中的Calendar类add和set方法的区别
  9. 计算机网络传输速率单位MB,计算机网络中,传输速率MB/s和Gb/s如何换算?
  10. 【Word】Word公式导出PDF后出现井号括号#()错误
  11. 大白菜装机教程win10_大白菜U盘启动工具|大白菜超级U盘启动制作工具 V6.0_2009.25官方版下载...
  12. 不低调的巨人,史玉柱
  13. python之HTML-块级标签
  14. FPGA电子设计系统的资源优化(面积优化)与速度优化
  15. Metabase新一代自助数据探索型开源BI
  16. 小程序笔记(四)发表评论或者普通发帖
  17. 易助工资总额管控产品介绍
  18. Windows认证基础知识
  19. android扫雷需求分析,扫雷需求分析.doc
  20. Maekdown使用

热门文章

  1. Unable to evaluate the expression Method threw ‘net.sf.json.JSONException‘ exception.
  2. matlab三维立体空间图,三维空间作图.ppt
  3. 虚拟化操作系统ESXi 6.7 迁移及克隆
  4. 乡村公路相连最后1公里,拼接
  5. 码农逆行被拦,跪下痛哭!
  6. SimpleFOC移植STM32(五)—— 电流采样及其变换
  7. 苹果邮件怎么添加qq邮箱_分别在win10自带邮件和iOS上添加QQ邮箱
  8. 怎么拷贝计算机桌面,怎么把电脑浏览器里的软件复制到桌面
  9. mongodb查询数据库表里总记录数count_documents()和获取记录里面的name字段的值docView[“name“].get_utf8().value.to_string()
  10. HTML之图像、表格