《Effective Java》------类和接口(2)

版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/hanxueyu666/article/details/78849494

一、接口优于抽象类

因为java值允许单继承,所以抽象类最为类型定义受到了极大的限制

1.1 使用接口,现有的类可以很容易被更新,以实现新的接口

因为类可以实现多个接口,一般来说,无法更新现有的类来扩展新的抽象类。如果你希望让两个类扩展同一个抽象类,就必须把抽象类放在层次的最高处,以便这两个类的一个祖先成为它的子类。这样做会间接地伤害到类层次,迫使这个公共祖先的所有后代类都扩展这个新的抽象类,无论他对于这些后代是否合适。


1.2 接口是定义mixin(混合类型)的理想选择。

不严格的来讲,mixin是指这样的类型:类除了实现它的“基本类型”之外,还可以实现这个mixin类型,以表明他提供了某些可供选择的行为。例如,Comparable是一个mixin接口,它允许类声明它的实例可以与其他的相互比较的对象进行排序。这个的接口之所以被称为mixin,是因为它允许任选的功能可被混合到类型的主要功能中。抽象类不能被用于定义mixin,同样也是因为他们不能被更新到现有类中:类不可能有一个以上的分类,类层次结构也没有适当的地方来插入mixin。


1.3 接口允许我们构造非层次结构的类型框架。

类型层次对于组织某些事物是非常合适的,但是其他有些事物并不能被整齐地组织成一个严格的层次结构。

例如,假设我们有一个接口代表一个singer,另外一个接口代表一个songwriter。

 public interface Singer {
        AudioClip sing(Song song);
    }

    public interface SongWriter {
        Song compose(boolean hit);
    }

在现实的生活中,有些歌唱家本身也是作曲家。因为我们使用了接口而不是抽象类来定义这些类型,所以对于单个类而言,它同时实现Singer和Songwrite是完全允许的。实际上我们可以定义第三个接口。


 public interface SingerSongWriter extends Singer,SongWriter{
        AudioClip strum();
        void actSensitive();
    }


虽然接口不允许包含方法的实现(当然jdk8以后允许),但是,使用接口来定义类型并不妨碍你未程序员提供实现上的帮助。通过对你的每个重要接口都提供一个骨架实现类,把接口和抽象类的优点结合起来。接口的作用仍然是定义类型,但是骨架实现类接管所有与接口实现相关的工作。

例如 Collections Framework为每个重要的集合接口都提供了一个骨架实现,包括AbstactionCollection、AbstractSet、AbstractList和AbstactMap。


二、接口只用于定义类型

常亮接口模式是对接口的不良使用
类在内部使用某些常量,这纯粹是实现细节。实现常量接口,会导致把这样的实现细节泄漏到该类的导出API中。类实现常量接口,这对于这个类的用户来讲并没有神价值。


三、类层次优于标签类

没看懂什么意思。


四、用函数对象表示策略

函数指针的主要用途就是实现策略模式。为了在Java中实现种子模式,要声明一个接口来表示该策略,并且为每个具体策略声明一个实现了该接口的类。当一个具体的策略只被使用一次时,通常使用匿名内部类来声明和实例化这个具体策略类。当一个具体策略是设计用来重复使用的时候,它的类通常要被实现为私有的静态成员,并通过共有的静态final域被导出,其类型为该策略接口。

例1:

1
2
3
4
5
Arrays.sort(StringArray, new  Comparator<String>(){
     public  int  compare(String s1, String s2) {
         return  s1.length() - s2.length();
     }
});

例2:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public  class  Host {
     private  static  class  StrLenCmp  implements  Comparator<String>,Serializable{
 
         @Override
         public  int  compare(String s1, String s2) {
             return  s1.length() - s2.length();
         }
         
     }
     
     public  static  final  Comparator<String> STRING_LENGTH_COMPARATOR =  new  StrLenCmp();
     
     public  static  void  main(String[] args) {
         String s1 =  "" ;
         String s2 =  "" ;
         int  result = Host.STRING_LENGTH_COMPARATOR.compare(s1, s2);
         System.out.println(result);
     }
}

五。优先考虑静态成员类

     嵌套类是指定义在另一个类内部的类,嵌套类只为它的外围类提供服务。嵌套类分为四种:静态成员类、非静态成员类、匿名类和局部类(后面三种称为内部类)。

        如果一个嵌套类的实例可以在它外部类的实例之外独立存在,则这个嵌套类应该设置成静态成员类(即:如果你声明的成员类不要求访问外围实例,就要始终把static修饰符放在它的声明中)。

        匿名类的用法:

        1、创建一个函数对象;

        2、创建过程对象;

        3、在静态工厂方法的内部使用;

        4、在复杂的类型安全枚举类型(它要求为每个实例提供单独的子类)中,用于公有的静态final域的初始化器中;

        简而言之,共有四种不同的嵌套类,每一种都有自己不同的用途。如果一个嵌套类需要在单个方法之外仍然是可见的,或者它太长了,不适合于放在一个方法内部,就应该使用成员类。如果成员类的每个实例都需要一个指向其外围实例的引用,就要把成员类做成非静态的;否则就做成静态的,假设一个嵌套类属于一个方法的内部,如果你只需要在一个地方创建它的实例,并且已经有了一个预先存在的类型可以说明这个类的特征,则把它做成匿名类;否则就做成局部类

猜你喜欢

转载自blog.csdn.net/hanxueyu666/article/details/78849494
今日推荐