EffectiveJava2_Item18接口优于抽象类

1.java提供实现接口+继承抽象类两种方式可以用来定义允许多个实现的类型,也就是被扩展。

·采用继承抽象类的方式

缺点:会破坏类的层次结构。单继承所导致

优点:

  1)可以提供使用者(子类)实现上的帮助。我的理解就是在抽象类中提供公共方法啦、定义提公共属性啦、提供模板方法

     啦(模板方法模式实际就是利用继承机制的设计模式)、组织基础方法提供通用的更加有用的方法啦。

  2)使用抽象类来定义类型比使用接口定义类型有一个明显的优势:抽象类应对将来的变化比接口要容易的多。如果以后在

     抽象层增加新方法,抽象类始终可以增加具体的方法,并且他包含默认的实现,子类如果想提供新的行为,可以直接

     override此方法,这样做不会对不想具有此方法的子类带来影响。相反,如果采用接口作为抽象层的话,这么做显然行

     不通:如果在接口中增加新方法,会直接影响到实现该接口的所有类,导致子类无法通过编译。所以设计接口时一定要

     非常谨慎。

·采用实现接口的方式

优点:

  1)现有的类可以很容易的实现新的接口,无论类在类层次结构的什么位置,并且不会对实现接口的类的父类产生影响,只

     会对其子类产生影响。

  2)接口是定义混合类型的理想选择。混合类型我的理解就是除了类 is-a 的类型(该类的类型)之外类通过实现某一接口  

     所具有的该接口的“行为”类型。

缺点:无法像继承抽象类一样为使用者(实现接口的类)提供实现上的帮助。

2.骨架实现类

   1)引入:为了既能享受抽象类所带来的优点(上述),又能具有接口带来的好处。

   2)实现:接口用于定义类型、骨架实现类实现接口(其实就是一个实现了该类型接口的抽象类)

              ·认真研究接口,缺定哪些方法是最基本的(其他方法可以根据他们来实现),这些基本的方法为骨架实现类的

                 抽象方法,交由其子类去实现。

              ·在骨架实现类中为接口中其他方法提供具体的实现。

              ·可以根据基础方法或者接口中其他方法在骨架实现类中定义其他有用的通用方法供子类使用。

              ·如果预置的类无法扩展骨架实现类(比如该类已经存在于某一类层次结构中)则仍然可以直接去实现接口。并

                 且骨架实现类仍然能有助于这样的类去实现接口。具体方式为:实现这个接口的类在实现接口中方法时可以通

                 过包装转发机制,将方法的调用转发到一个内部私有的类的实例上,这个内部私有的类继承自骨架实现类。

   3)优点:骨架实现为抽象类提供了实现上的帮助,但又不强加“抽象类被用做类型定义时”所持有的严格限制。(除了通

               过继承手段增加功能以外别无他法)

   3)例子:先看看比较简单的骨架实现类的一个基本实现例子

定义一个通用接口

package com.gmail.mazhongjia.abstractInterface;

/**
 * 接口
 */
public interface Interface {

	void primitiveMethodA();
	
	void primitiveMethodB();
	
	void otherMethodC();
	
	void otherMethodD();
}

 

下面是骨架实现类

package com.gmail.mazhongjia.abstractInterface;

/**
 * 骨架实现类
 */
public abstract class AbstractClass implements Interface{

	//其他方法需要在骨架实现类中实现
	@Override
	public void otherMethodC() {
		//dosomething
	}

	@Override
	public void otherMethodD() {
		//dosomething
	}
	
	//其他通用方法
	public void otherMethodE(){
		primitiveMethodA();
		primitiveMethodB();
		otherMethodC();
	}
	
	//基础的方法交由子类实现
	@Override
	public abstract void primitiveMethodA();

	@Override
	public abstract void primitiveMethodB();

}

 

最后是子类

package com.gmail.mazhongjia.abstractInterface;

public class Sub extends AbstractClass implements Interface {

	//实现基础方法
	@Override
	public void primitiveMethodA() {
	}

	@Override
	public void primitiveMethodB() {
	}
}

 

再来看一个直接实现接口的例子,其中接口、骨架实现类不变

下面是子类 

package com.gmail.mazhongjia.abstractInterface;

/**
 * 外围类直接实现接口 并把对接口中方法的调用转发给PrivateClass类的实例上
 */
public class Sub2 extends OtherClass implements Interface{
	
	private PrivateClass privateClass;
	
	Sub2(){
		privateClass = new PrivateClass();
	}

	@Override
	public void otherMethodC() {
		privateClass.otherMethodC();
	}

	@Override
	public void otherMethodD() {
		privateClass.otherMethodD();
	}

	@Override
	public void primitiveMethodA() {
		privateClass.primitiveMethodA();
	}

	@Override
	public void primitiveMethodB() {
		privateClass.primitiveMethodB();
	}
	
	/**
	 * 通过内部类实现骨架实现类中基础方法(也是模拟多重继承的方式)
	 */
	private class PrivateClass extends AbstractClass{

		@Override
		public void primitiveMethodA() {
		}

		@Override
		public void primitiveMethodB() {
		}
	}
}

3.结论

·接口通常是定义允许多个实现的类型的最佳途径。除非当演变的容易性比灵活性和功能更为重要的时候。

·如果你导出了一个重要的接口,就应该坚决考虑同时为此接口提供骨架实现类。

·应该尽可能谨慎地设计所有的公有接口,并通过编写多个实现来对他们进行全面的测试。

 

你可能感兴趣的:(设计模式,Gmail)