在程序设计过程中,读者很可能遇到这样一种窘境:设计了一个接口,但实现这个接口的子类并不需要实现接口中的全副办法,也就是说,接口中的办法过多,对于某些子类是多余的,咱们不得不节约的写上一个空的实现。
明天小菜提到的“形象接口”,就是用来解决这个问题的。为了不误导读者,先阐明一下,什么是“形象接口”。所谓“形象接口”,即在提供接口的同时,提供一个抽象类,用抽象类实现该接口(实际上这是缺省适配模式)。上面小菜举个例子,让读者领会这样做的益处。代码写的不咋地,为了避免读者看不懂,先上一张类图:
具体代码:
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 子类没有间接实现接口,而是通过继承抽象类间接实现接口,这样益处一下就体现进去了!
向接口中新增的办法,能够在实现接口的抽象类中缓冲一下,提供一个默认的实现,这样一来,就不用强制所有的子类 (通过继承抽象类间接实现接口的类) 都进行批改,能够形象的了解为“没有轰动子类”。而须要应用这个办法的子类,间接重写即可。
小菜感叹:
人类的智慧真平凡!数组和链表联合,产生了高效的哈希表;接口和抽象类联合,产生了优雅的缺省适配模式。大家致力吧!!!
写在前面的话:
世间没有完满的事物,设计模式也是如此,过多的探讨优缺点没有意义,适合的就是最好的,什么是适合的呢?这才是体现智慧的中央。