Effective Java 34 Emulate extensible enums with interfaces
|
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
- 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);
}
}
- 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
- Passing the extended enums between methods.
- 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的更多相关文章
- 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 ...
- 《Effective Java》读书笔记 - 6.枚举和注解
Chapter 6 Enums and Annotations Item 30: Use enums instead of int constants Enum类型无非也是个普通的class,所以你可 ...
- Effective Java 目录
<Effective Java>目录摘抄. 我知道这看起来很糟糕.当下,自己缺少实际操作,只能暂时摘抄下目录.随着,实践的增多,慢慢填充更多的示例. Chapter 2 Creating ...
- 【Effective Java】阅读
Java写了很多年,很惭愧,直到最近才读了这本经典之作<Effective Java>,按自己的理解总结下,有些可能还不够深刻 一.Creating and Destroying Obje ...
- Effective Java 第三版——34. 使用枚举类型替代整型常量
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- Effective Java 第三版——38. 使用接口模拟可扩展的枚举
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- Effective Java 第三版笔记(目录)
<Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将近8年的时 ...
- [Effective Java]第八章 通用程序设计
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
- Effective Java通俗理解(下)
Effective Java通俗理解(上) 第31条:用实例域代替序数 枚举类型有一个ordinal方法,它范围该常量的序数从0开始,不建议使用这个方法,因为这不能很好地对枚举进行维护,正确应该是利用 ...
随机推荐
- nodejs morgan包
新建app.js var express = require('express') var logger = require('morgan') var app = express() app.use ...
- [linux]执行pip安装的程序:command not found
执行pip安装的程序:command not found 问题描述: 我有一台阿里云服务器,上面装的是centos系统,我用pip安装好vituralenv,都没办法直接启动.同样 我今天在部署我的t ...
- n 后问题
n后问题,解决思路:假设每个皇后占一行(且第i个皇后放在第i - 1 行),依次去尝试下一个皇后该放在该行的哪一列 #include<iostream> #include<cmath ...
- JS&CSS文件请求合并及压缩处理研究(一)
在我们日常的网站开发工作中,一个页面难免会引用到各种样式及脚本文件.了解Web开发的朋友们都知道,页面引用的每一个: <link href="style.css" rel=& ...
- ASP.NET高并发解决方案
一.页面静态化: 二.运用WCF,WEB SERVICE等技术实现分布式业务逻辑处理及数据访问的能力: 三.页面缓存: 四.数据缓存: 五.建立图片文件服务器:
- 一起Polyfill系列:让Date识别ISO 8601日期时间格式
一.什么是ISO 8601日期时间格式 ISO 8601是国际标准化组织制定的日期时间表示规范,全称是<数据存储和交换形式·信息交换·日期和时间的表示方法>. 示例: 1. 2014-12 ...
- Parameter配置文件获取
public class ConfigInfo { public static ParametersHelper Parameters { get { return new ParametersHel ...
- Mongodb:修改文档结构后出现错误:Element '***' does not match any field or property of class ***.
Mongodb:修改文档结构后出现错误:Element '***' does not match any field or property of class ***. Mongodb是一种面向文档的 ...
- Python入门笔记(21):Python函数(4):关于函数式编程的内建函数
一.关于函数式编程的内建函数 apply()逐渐被舍弃,这里不讨论 1.filter() #filter(func,seq) """纯Python描述filter函数&q ...
- 35 Gallery – Ajax Slide
http://html5up.net/overflow (PC,Mobile,Table) http://bridge.net/ https://github.com/bridgedotnet/Bri ...