我正在尝试将Java泛型用于我的特定用例。有一个通用类Node
,在这个例子中会有很多像NodeBoolean
这样的实现类。
public abstract class Node<T>
{
T defaultValue;
public Node(T defaultValue) {
this.defaultValue = defaultValue;
}
protected abstract T parse(String input) ;
public T getValue()
{
try
{
// here will be some logic to get String value from some db or any other source
String input = "true";
return parse(input);
} catch (Exception e) {
return defaultValue;
}
}
}
实施班级
class NodeBoolean extends Node<Boolean>
{
public NodeBoolean(Boolean defaultValue) {
super(defaultValue);
}
@Override
protected Boolean parse(String input) {
return Boolean.parseBoolean(input);
}
}
测试类
class TestNode
{
public static void main(String[] args) {
NodeBoolean node = new NodeBoolean(true);
System.out.println(node.getValue());
}
}
我使用这种方法遇到的问题
假设类Node
的构造函数有多种变体,那么所有实现类也需要定义它们以实现可见性。使用Builder模式可以解决这个问题,但我只是想知道其他可能的解决方案。
将会有很多实现类只有一个覆盖方法parse
。我正在寻找一种在泛型类instanceof
本身的给定示例中基于defaultValue
Node
来定义所有不同解析器的方法。然后,此Node
课程不是abstract
。
我希望在创建parse
对象时,提供定义String
方法的功能,该方法需要T
并根据用户需求返回Node
的值阶级本身。通过这种方式,如果我只有一次特定对象类型Node
可以创建,而无需定义任何新的实现类。
我正在寻找解决3个以上问题的解决方案。如果我在任何时候都不清楚,请告诉我。
答案 0 :(得分:3)
我认为暴露构造函数,或使用构建器或工厂模式是这里唯一的可能性。但是,下一个答案可以减轻这种情况。
为什么不将函数传递给处理解析的节点,而不是将parse
方法作为抽象?
public class Node<T> {
private T defaultValue;
private Function<String, T> parser;
public Node(T defaultValue,
Function<String, T> parser) {
this.defaultValue = defaultValue;
this.parser = parser;
}
public T getValue()
{
// depending on the parser, re-parsing every time this is called could get expensive!
try
{
// here will be some logic to get String value from some db or any other source
String input = "true";
return parser.apply(input);
} catch (Exception e) {
return defaultValue;
}
}
}
您现在可以通过执行此操作来创建节点
Node<Boolean> node = new Node<>(s -> Boolean.parseBoolean(s))
您还可以在解析器函数中设置默认值,无需将其存储在节点中 - 这取决于您的要求。
修改强> 我在这里使用Java 8的Function接口和lambdas,但您可以通过定义自己的Function接口在Java 1.0中轻松完成此操作。
public interface Function<I, O> {
O apply(I);
}
然后以某种方式实现它 - 具体类,匿名类等 - 根据您需要进行的解析所需。
Node<Boolean> node = new Node<>(new Function<String, Boolean>() {
public Boolean apply(String s) {
return Boolean.parseBoolean(s);
}
});
编辑2
在回复有关预定义类型的评论时,您可以采取一些不同的方法。
public class NodeFactory {
private static final Function <String, Boolean> BOOLEAN_PARSER = s -> Boolean.parseBoolean(s);
.// plus more for integers, double, etc, as required
private NodeFactory() {
// no-op
}
public static Node<Boolean> booleanNode(boolean defaultValue){
return new Node<Boolean>(defaultValue,
BOOLEAN_PARSER);
}
// plus more for integer, double, etc, as required
}
或者你可以采取延伸路线
public class BooleanNode extends Node<Boolean> {
public BooleanNode(boolean defaultValue) {
super(defaultValue,
s -> Boolean.parseBoolean(s)); // or use a static parser as in the factory example
}
}
在任何情况下,保持Node
非抽象可以为您的用户提供很大的灵活性,但您的用例可能不需要。
答案 1 :(得分:0)
您是否需要延长Node
课程?或者只是简单地创建一个匿名类?它实际上是允许用户定义解析方法&#34;
Node<Boolean> booleanNode = new Node<Boolean>(true) {
@Override
protected Boolean parse(String input) {
return Boolean.parseBoolean(input);
}
};
也许我们可以有一个Factory类来提供这些Node
类:
class NodeFactory {
public <T> static createNode(Class<T> classType) {
if (classType == Boolean.class) {
return newBooleanNode();
} else if (classType == Integer.class){
return newIntegerNode();
}
}
private Node<Boolean> newBooleanNode() {
return new Node<Boolean>(true) {
@Override
protected Boolean parse(String input) {
return Boolean.parseBoolean(input);
}
}
}
private Node<Integer> newIntegerNode() {
return new Node<Integer>(0) {
@Override
protected Boolean parse(String input) {
return Integer.parseInt(input);
}
}
}
}
在客户端,我们将有以下
Node<Boolean> booleanNode = NodeFactory.createNode(Boolean.class);
Node<Integer> integerNode = NodeFactory.createNode(Integer.class);