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. 一个android应用开发的感悟

    对于客户端的开发,以我个人现在的水准,很难进行一个系统的讲解,只能分享下遇到的几个问题点好了! 1:对于tabhost的使用,这个东西真的是过时了:第一个版本,我是用的tabhost确实是很难用,不过 ...

  2. UWP开发入门(十六)——常见的内存泄漏的原因

    本篇借鉴了同事翔哥的劳动成果,在巨人的肩膀上把稿子又念了一遍. 内存泄漏的概念我这里就不说了,之前<UWP开发入门(十三)——用Diagnostic Tool检查内存泄漏>中提到过,即使有 ...

  3. Android程序ToDoList

    本文的目的是创建一个简单的ToDoList列表. 这个应用的功能是记录我的代办事项,简单到不需要本地存储,所有的代办事项都只是存储在内存中,就是只有程序打开的时候可以增加查看代办事项,当程序关闭的时候 ...

  4. 汇编学习:float与double速度问题

    X86处理器包含两种类型的浮点数寄存器.第一种使用8个浮点寄存器组成浮点寄存器栈,另一种为向量寄存器(XMM,YMM),它们对于单双精度的处理是不同的.本文将讨论两种模式下的浮点数计算速度问题. 一. ...

  5. mysqldump命令的常用组合

    只导表结构完整语句: mysqldump -h192.168.1.174  --port=3306 -uroot -p  --routines --events --no-data  --no-cre ...

  6. 2015腾讯暑期实习生 Web前端开发 面试经历

    [2015腾讯暑期实习生 Web前端开发 面试经历] 好吧,首先声明,我被刷了,应该是跪在二面 微信查到的面试状态一直呈现复试中 .. 整整四天了.. 看来是没希望了 不过也是一次经历,记录一下还是可 ...

  7. Linux - Ubuntu下JDK配置

    系统版本: ubuntu 14.04 x64JDK版本: jdk-8u60-linux-x64 1.查看系统位数,输入以下命令即可 getconf LONG_BIT 2.下载对应的JDK文件,我这里下 ...

  8. 重构if...else...或者switch程序块

    我们在开发asp.net时,经常有使用if...else...或者是使用switch来进行多个条件判断.如下面这篇<用户控件(UserControl) 使用事件 Ver2>http://w ...

  9. Winform开发框架之客户关系管理系统(CRM)的开发总结系列4-Tab控件页面的动态加载

    在前面介绍的几篇关于CRM系统的开发随笔中,里面都整合了多个页面的功能,包括多文档界面,以及客户相关信息的页面展示,这个模块就是利用DevExpress控件的XtraTabPage控件的动态加载实现的 ...

  10. .Net一般处理程序来实现用户名的验证

    一般处理程序 在说一般处理程序之前,先来看看什么是aspx.在vs中,使用的大多是aspx页面.aspx页面就是在接收到一个请求之后,将返回的结果生成一个html页面返回给服务器.当我们有时候需要自己 ...