Advantage

Disadvantage

Enum types

Clarity

Safety

Ease of maintenance.

None extensibility

Typesafe enum pattern(Interfaces to emulate extensible enums)

Extensibility

No good way to enumerate all of the elements of a base type and its extension.

Extensibility would complicate many aspects of the design and implementation.

Implementations cannot be inherited from one enum type to another.

Scenario

Sometimes it is desirable to let the users of an API provide their own operations, effectively extending the set of operations provided by the API.

Compelling use case for extensible enumerated type -- Operation codes/ opcodes.

Usage

  1. Pass a single instance of an "extension enum" anywhere a "base enum" is expected.

    /**

    * Demo for "34 Emulate extensible enums with interfaces".

    */

    package com.effectivejava.EnumAnnotations;

    /**

    * @author Kaibo

    *

    */

    public interface Operation {

    double apply(double x, double y);

    }

    /**

    * Demo for the "34 Emulate extensible enums with interfaces".

    */

    package com.effectivejava.EnumAnnotations;

    import java.util.HashMap;

    import java.util.Map;

    /**

    * @author Kaibo

    *

    */

    public enum BaseOperation implements Operation {

    PLUS("+") {

    public double apply(double x, double y) {

    return x + y;

    }

    },

    MINUS("-") {

    public double apply(double x, double y) {

    return x - y;

    }

    },

    TIMES("*") {

    public double apply(double x, double y) {

    return x * y;

    }

    },

    DIVIDE("/") {

    public double apply(double x, double y) {

    return x / y;

    }

    };

    private final String symbol;

    BaseOperation(String symbol) {

    this.symbol = symbol;

    }

    @Override

    public String toString() {

    return symbol;

    }

    public abstract double apply(double x, double y);

    // Implementing a fromString method on an enum type

    private static final Map<String, BaseOperation> stringToEnum = new HashMap<String, BaseOperation>();

    static { // Initialize map from constant name to enum constant

    for (BaseOperation op : values())

    stringToEnum.put(op.toString(), op);

    }

    // Returns BaseOperation for string, or null if string is invalid

    public static BaseOperation fromString(String symbol) {

    return stringToEnum.get(symbol);

    }

    }

  2. Pass in an entire extension enum type and use its elements in addition to or instead of those of the base type.

/**

* Demo for the "34 Emulate extensible enums with interfaces".

*/

package com.effectivejava.EnumAnnotations;

/**

* @author Kaibo

*

*/

public enum ExtendedOperation implements Operation {

EXP("^") {

public double apply(double x, double y) {

return Math.pow(x, y);

}

},

REMAINDER("%") {

public double apply(double x, double y) {

return x % y;

}

};

private final String symbol;

ExtendedOperation(String symbol) {

this.symbol = symbol;

}

@Override

public String toString() {

return symbol;

}

}

Note

  1. Passing the extended enums between methods.
    1. Bounded type token

      public static void main(String[] args) {

      double x = Double.parseDouble(args[0]);

      double y = Double.parseDouble(args[1]);

      test(ExtendedOperation.class, x, y);

      }

      private static <T extends Enum<T> & Operation> void test(

      Class<T> opSet, double x, double y) {

      for (Operation op : opSet.getEnumConstants())

      System.out.printf("%f %s %f = %f%n", x, op, y, op.apply(x, y));

      }

b. Passing with Collection<? Extends Operation>

public static void main(String[] args) {

double x = Double.parseDouble(args[0]);

double y = Double.parseDouble(args[1]);

test(Arrays.asList(ExtendedOperation.values()), x, y);

}

private static void test(Collection<? extends Operation> opSet, double x, double y) {

for (Operation op : opSet)

System.out.printf("%f %s %f = %f%n", x, op, y, op.apply(x, y));

}

2. The logic to store and retrieve the symbol associated with an operation is duplicated in BasicOperation and ExtendedOperation. In this case it doesn't matter because very little code is duplicated. If there were a larger amount of shared functionality, you could encapsulate it in a helper class or a static helper method to eliminate the code duplication.

Summary

While you cannot write an extensible enum type, you can emulate it by writing an interface to go with a basic enum type that implements the interface.

Effective Java 34 Emulate extensible enums with interfaces的更多相关文章

  1. Effective Java Index

    Hi guys, I am happy to tell you that I am moving to the open source world. And Java is the 1st langu ...

  2. 《Effective Java》读书笔记 - 6.枚举和注解

    Chapter 6 Enums and Annotations Item 30: Use enums instead of int constants Enum类型无非也是个普通的class,所以你可 ...

  3. Effective Java 目录

    <Effective Java>目录摘抄. 我知道这看起来很糟糕.当下,自己缺少实际操作,只能暂时摘抄下目录.随着,实践的增多,慢慢填充更多的示例. Chapter 2 Creating ...

  4. 【Effective Java】阅读

    Java写了很多年,很惭愧,直到最近才读了这本经典之作<Effective Java>,按自己的理解总结下,有些可能还不够深刻 一.Creating and Destroying Obje ...

  5. Effective Java 第三版——34. 使用枚举类型替代整型常量

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  6. Effective Java 第三版——38. 使用接口模拟可扩展的枚举

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  7. Effective Java 第三版笔记(目录)

    <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将近8年的时 ...

  8. [Effective Java]第八章 通用程序设计

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  9. Effective Java通俗理解(下)

    Effective Java通俗理解(上) 第31条:用实例域代替序数 枚举类型有一个ordinal方法,它范围该常量的序数从0开始,不建议使用这个方法,因为这不能很好地对枚举进行维护,正确应该是利用 ...

随机推荐

  1. UNIQUEIDENTIFIER列上的统计信息

    UNIQUEIDENTIFIER列上的统计信息非常有意思,在它上面有一些很令人讨厌的行为.我们来看下. 问题重现(The repro) 为了向你展示我们刚抱怨的行为,我用下列简单的表定义创建了一个数据 ...

  2. Python装饰器由浅入深

    装饰器的功能在很多语言中都有,名字也不尽相同,其实它体现的是一种设计模式,强调的是开放封闭原则,更多的用于后期功能升级而不是编写新的代码.装饰器不光能装饰函数,也能装饰其他的对象,比如类,但通常,我们 ...

  3. SecureCRT连接linux设置vim显示颜色

    只需要两个步骤: 1) 选项 --> 会话选项 --> 终端 --> 仿真 -->  勾选“ANSI 颜色”. 2)  在.bashrc中添加:export TERM=xter ...

  4. [操作系统实验lab2]实验报告

    static void * alloc(u_int n, u_int align, int clear) { extern char end[]; int i; u_long alloced_mem; ...

  5. 组合数学 - 置换群的幂运算 --- poj CARDS (洗牌机)

    CARDS Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 1448   Accepted: 773 Description ...

  6. WebService服务调用方法介绍

    1 背景概述 由于在项目中需要多次调用webservice服务,本文主要总结了一下java调用WebService常见的6种方式,即:四种框架的五种调用方法以及使用AEAI ESB进行调用的方法. 2 ...

  7. 关于iPhone多点触控

    虽然这个问题很简单,但是对于我这接触两天的菜鸟来说也弄了很久,网上又找不到相关的解决方法,避免其他人和我一样,还是记录一下 一般网上找到的教程是这么教: -(void )touchesBegin:(N ...

  8. sql where 1=1和 0=1 的作用

    sql where 1=1和 0=1 的作用 摘自: http://www.cnblogs.com/junyuz/archive/2011/03/10/1979646.html where 1=1; ...

  9. Xcode配置libdc1394

    libdc1394是一个开源库,提供了一个Mac下完整的1394相机编程接口,这篇文章将介绍Xcode如何配置该库. 步骤: 1.下载libdc1394的源码,并解压 http://damien.do ...

  10. java判定字符串中仅有数字和- 正则表达式匹配 *** 最爱那水货

    1.当有其他字符出现时,返回的数组长度>1 String s = "3---6\\5656";        Pattern pattern = Pattern.compil ...