java 设计模式-缺省适配器模式
本文转载地址:http://www.cnblogs.com/iyangyuan/archive/2013/03/11/2954808.html
在程序设计过程中,读者很可能遇到这样一种困境:设计了一个接口,但实现这个接口的子类并不需要实现接口中的全部方法,也就是说,接口中的方法过多,对于某些子类是多余的,我们不得不浪费的写上一个空的实现。
今天小菜提到的“抽象接口”,就是用来解决这个问题的。
为了不误导读者,先说明一下,什么是“抽象接口”。
所谓“抽象接口”,即在提供接口的同时,提供一个抽象类,用抽象类实现该接口(实际上这是缺省适配模式)。
下面小菜举个例子,让读者体会这样做的好处。
代码写的不咋地,为了防止读者看不懂,先上一张类图:

具体代码:
ITestInterface.java

1 /*
2 假设有一个顶层接口
3 */
4 public interface ITestInterface{
5 void method1();
6 int method2();
7 boolean method3();
8 }

TestAbstract.java

1 /*
2 抽象类abstract实现了ITestInterface顶层接口
3 */
4
5 public abstract class TestAbstract implements ITestInterface{
6 //找出接口中必要的方法,也就是子类必须实现的方法,定义成抽象方法,交由子类实现
7 public abstract void method1();
8 public abstract int method2();
9
10 //一些独特的方法可以在抽象类中默认实现
11 public boolean method3(){
12 return true;
13 }
14 }

TestClass1.java

1 /*
2 普通类TestClass1继承了TestAbstract抽象类
3 */
4
5 public class TestClass1 extends TestAbstract{
6
7 //TestClass1必须实现抽象的method1方法,该方法最早是接口中定义的
8 public void method1(){
9
10 }
11 //TestClass1必须实现抽象的method2方法,该方法最早是接口中定义的
12 public int method2(){
13 return 1;
14 }
15
16 //接口中的method3方法对于TestClass1无关紧要,因此不做重写。
17 }

TestClass2.java

1 /*
2 普通类TestClass2继承了TestAbstract抽象类
3 */
4
5 public class TestClass2 extends TestAbstract{
6
7 //TestClass2必须实现抽象的method1方法,该方法最早是接口中定义的
8 public void method1(){
9
10 }
11 //TestClass2必须实现抽象的method2方法,该方法最早是接口中定义的
12 public int method2(){
13 return 2;
14 }
15
16 //method3方法对于TestClass2来说至关重要,因此必须重写。
17 public boolean method3(){
18 return false;
19 }
20
21 }

代码精讲:
从以上例子可以看出,最高层的接口被一个抽象类实现,在抽象类中,我们把关键的method1、method2方法定义成抽象方法,强制子类去实现,而“独特”的method3方法在抽象类中做一个默认实现。
等到TestClass1、TestClass2继承TestAbstract抽象类时,优势就体现出来了,TestClass1、TestClass2必须实现method1、method2,但如果用不到method3,可以直接无视。
通过接口和抽象类的结合,避免了在实现接口的子类中出现大量的“无意义”实现,这个“无意义”实现,被缓冲到了抽象类中,完美展现了代码复用(可以把抽象类理解成接口和实现类之间的缓冲)。
需要指出的是,我们既可以选择继承抽象类,也可以选择实现接口,并不是说一定要继承抽象类,看情况而定,这里是两种选择,两个机会。
写到这,或许读者觉得文章已经结束了,其实没有。。。
这样做的好处不仅仅是这一点,细细品味,假如我们向接口中增加了一个方法。。。
具体代码:
温馨提示:不要被代码吓到,其实这些代码和上边的差不多,只不过加了个方法而已。
ITestInterface.java

1 /*
2 假设有一个顶层接口
3 */
4 public interface ITestInterface{
5 void method1();
6 int method2();
7 boolean method3();
8 //接口中新增加了方法
9 String method4();
10 }

TestAbstract.java

1 /*
2 抽象类abstract实现了ITestInterface顶层接口
3 */
4
5 public abstract class TestAbstract implements ITestInterface{
6 //找出接口中必要的方法,也就是子类必须实现的方法,定义成抽象方法,交由子类实现
7 public abstract void method1();
8 public abstract int method2();
9
10 //一些独特的方法可以在抽象类中默认实现
11 public boolean method3(){
12 return true;
13 }
14
15 //抽象类中提供一个默认实现,这样就可以避免"惊动"所有子类
16 public String method4(){
17 return "";
18 }
19 }

TestClass1.java

1 /*
2 普通类TestClass1继承了TestAbstract抽象类
3 */
4
5 public class TestClass1 extends TestAbstract{
6
7 //TestClass1必须实现抽象的method1方法,该方法最早是接口中定义的
8 public void method1(){
9
10 }
11 //TestClass1必须实现抽象的method2方法,该方法最早是接口中定义的
12 public int method2(){
13 return 1;
14 }
15
16 //接口中的method3方法对于TestClass1无关紧要,因此不做重写。
17
18 //新增的方法对于TestClass1来说至关重要,因此必须重写
19 public String method4(){
20 return "Class1";
21 }
22
23 }

TestClass2.java

1 /*
2 普通类TestClass2继承了TestAbstract抽象类
3 */
4
5 public class TestClass2 extends TestAbstract{
6
7 //TestClass2必须实现抽象的method1方法,该方法最早是接口中定义的
8 public void method1(){
9
10 }
11 //TestClass2必须实现抽象的method2方法,该方法最早是接口中定义的
12 public int method2(){
13 return 2;
14 }
15
16 //method3方法对于TestClass2来说至关重要,因此必须重写。
17 public boolean method3(){
18 return false;
19 }
20
21 //新增的方法对于TestClass2来说无关紧要,无需知道新增method4的存在
22 }

代码精讲:
这段代码演示了假如项目已经成型,但是需求有变,我们不得不向接口中增加一个新的方法,假如子类直接实现了接口,那么这些子类都要修改,来实现接口新增的方法。
但本例中的TestClass1、TestClass2子类没有直接实现接口,而是通过继承抽象类间接实现接口,这样好处一下就体现出来了!
向接口中新增的方法,可以在实现接口的抽象类中缓冲一下,提供一个默认的实现,这样一来,就不必强制所有的子类(通过继承抽象类间接实现接口的类)都进行修改,可以形象的理解为“没有惊动子类”。而需要使用这个方法的子类,直接重写即可。
小菜感慨:
人类的智慧真伟大!数组和链表结合,产生了高效的哈希表;接口和抽象类结合,产生了优雅的缺省适配模式。大家努力吧!!!
写在后面的话:
世间没有完美的事物,设计模式也是如此,过多的讨论优缺点没有意义,合适的就是最好的,什么是合适的呢?这才是体现智慧的地方。
java 设计模式-缺省适配器模式的更多相关文章
- Java设计模式--缺省适配器模式
我认为这个模式比较常见,还记得我们学习Swing的时候吗,有没有见过很多Adapter?那时候不知道Adapter的意义所在,但至少知道他能够省去我们不需要的实现. 这个社会有N中职业(job),但是 ...
- 重学 Java 设计模式:实战适配器模式
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 擦屁屁纸80%的面积都是保护手的! 工作到3年左右很大一部分程序员都想提升自己的技术 ...
- Java设计模式系列之适配器模式
适配器模式的定义 将一个类的接口转换成客户希望的另外一个接口.Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作.(就类似于我们充电器的转接头将220V的电压转换成我们的手机端 ...
- 《JAVA设计模式》之适配器模式(Adapter)
在阎宏博士的<JAVA与模式>一书中开头是这样描述适配器(Adapter)模式的: 适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能 ...
- Java设计模式7:适配器模式
适配器模式 适配器模式说的是,可以把一个类的接口变换成客户端所期待的另一种接口,使得原本因接口不匹配而无法在一起工作的两个类可以一起工作. 适配器模式的用途 适配器模式的用途,在网上找了一幅图,挺形象 ...
- java设计模式笔记(1)-适配器模式
适配器的定义 适配器就是一个接口转换器,它可以是一个独立的硬件接口设备,允许硬件或电子接口与其它硬件或电子接口相连,也可以是信息接口.比如:电源适配器.三角架基座转接部件.USB与串口的转接设备等. ...
- java设计模式自我总结---适配器模式
上一篇博客说完了 java 23 中设计模式中的五种 创建性模式,由于篇幅过长,新开一贴今天开始学习结构型模式, 结构型模式包括以下七种:适配器模式.装饰模式.代理模式.外观模式.桥接模式.组合模式. ...
- JAVA设计模式初探之适配器模式
http://blog.csdn.net/jason0539/article/details/22468457 1. 概述 将一个类的接口转换成客户希望的另外一个接口.Adapter模式使得原本由于接 ...
- Java设计模式学习记录-适配器模式
前言 之前已经将五个创建型设计模式介绍完了,从这一篇开始介绍结构型设计模式,适配器模式就是结构型模式的一种,适配器要实现的效果是把“源”过渡到“目标”. 适配器模式 在开发过程中,使用一个已经存在的类 ...
随机推荐
- 如何用while循环输出十行十列变色★☆
输出十行十列星星 k = 0 #设置一个终止变量 while k < 10: i = 0 #设置一个满十换行变量 while i < 10: print('★',end='') i += ...
- 关于Springboot整合mybatis启动的问题
由于是刚pull下来的项目整体也不熟悉,然后项目无法正常启动,爆出的异常为: Invalid bound statement (not found) 这是由于创建的新模块mapper与扫描mapper ...
- 十一、Hadoop学习笔记————数据库与数据仓库
数据仓库是集成的面向主题的数据库的集合 面向主题主要是宏观上解决某一类问题,集合性指数据集 数据库主要处理用于事务处理,数据仓库用于分析处理,数据库适用于操作型数据,便于增删改查, 数据仓库则用于挖掘 ...
- 全内存的redis用习惯了?使用基于硬盘存储类似redis的nosql产品ssdb呢?
首先说一下背景,在双十一的时候,我们系统接受X宝的订单推送,同事原先的实现方式是使用redis的List作为推送数据的承载,在非大促的场景下, 一切运行正常,内存占用大概3-4G,机器是16G内存.由 ...
- Glance 镜像服务群集
#Glance 镜像服务群集 openstack pike 部署 目录汇总 http://www.cnblogs.com/elvi/p/7613861.html#4.Glance 镜像服务群集 ##. ...
- MySQL学习——基本命令(1)
MySQL添加新用户.为用户创建数据库.为新用户分配权限 参考博客http://blog.csdn.net/u013216667/article/details/70158452 一.登录MySQL ...
- 《Linux命令行与shell脚本编程大全》第二十六章 一些有意思的脚本
26.1 发送消息 26.1.1 功能分析 1.确定系统中都有谁 $who 给出的信息包括用户名 用户所在终端 用户登入系统的时间 2.启用消息功能 用户可以禁止别人给我发消息,所以需要先检查一下是否 ...
- Mysql主从原理
MySQL的Replication(英文为复制)是一个多MySQL数据库做主从同步的方案,特点是异步复制,广泛用在各种对mysql有更高性能.更高可靠性要求的场合.与之对应的是另一个同步技术是MySQ ...
- 禁止mui事件tab切换内容左右滑动
mui('.mui-slider').slider().setStopped(true);
- Redis的五种数据类型及方法
字符串string: 字符串类型是Redis中最为基础的数据存储类型,是一个由字节组成的序列,他在Redis中是二进制安全的,这便意味着该类型可以接受任何格式的数据,如JPEG图像数据货Json对象描 ...