如何在 java 中实现静态可扩展注册表



我试图实现一个静态注册表,该注册表可以通过第三方开发人员再次静态地将其项目添加到此注册表进行扩展。

我遇到了 Java 中描述的问题:使用静态初始值设定项块将类注册到全局静态注册表 - 但是,那里描述的注册注册每个类的建议不符合我的要求,因为在我的情况下,第三方开发人员只将我的库放在一个 jar 中,他们只能扩展它,向其添加额外的类,但不能修改我的 jar 中的任何内容。

如果可能的话,有什么建议可以实现这一目标吗?(应该是,我猜)

这是我所拥有的:

import java.util.HashMap;
public class Calculator {
public double eval(String symbol, double operand1, double operand2) {
return OperatorRegistry.get(symbol).calculate(operand1, operand2);
}
public static void main(String[] args) {
Calculator c = new Calculator();
System.out.println(c.eval("+", 3, 9));
System.out.println(c.eval("-", 13, 9));
}
}
class OperatorRegistry {
static HashMap<String, Operator> registry = new HashMap<String, Operator>();
public static void register(Operator o) {
System.out.println("Registering: " + o.getSymbol());
registry.put(o.getSymbol(), o);
}
public static Operator get(String c) {
return registry.get(c);
}
}
interface Operator {
public  String getSymbol() ;
public  double calculate(double a, double b) ;
}

class AddOperator implements Operator{
static {
OperatorRegistry.register(new AddOperator());
}
public  String getSymbol() {
return "+";
}
public  double calculate(double a, double b) {
return a + b;
}
}

class SubtractOperator implements Operator {
static {
OperatorRegistry.register(new SubtractOperator());
}
public  String getSymbol() {
return "-";
}
public  double calculate(double a, double b) {
return a - b;
}
}

如果我正确理解您的问题,您需要一个动态服务定位器模式,即使在运行时,您也可以在需要时执行。这意味着,如果有新符号并且有运算符的实现,它应该可以工作。我告诉你以下代码的基线。

public double eval(String symbol, double operand1, double operand2) {
return OperatorRegistry.get(symbol).calculate(operand1, operand2);
}

我的建议是维护这样的地图。

Map<String (Symbol), OperatorService(Operator Impl)> symbolOpServiceMap

必须有加载方法,无论是否是新符号,每次都会加载。我建议维护另一个具有符号和操作员服务类实现的xml或属性文件。如果分发 jar,请将 jar 与外部化的 xml、json 或属性文件一起分发,以便在运行时加载所有运算符服务。这意味着,您提供了静态和动态服务将始终加载的灵活性,并且您应该能够执行以下代码。

OperatorRegistry.get(symbol).calculate(operand1, operand2);

为了使其更干净,您应该具有以下结构。

public double eval(String symbol, double operand1, double operand2) {
loadAllOperatorServices();// <= This method will always be invoked and it //will read from xml, json file based upon the number of entries for symbol and //its corresponding implementation. 
return OperatorRegistry.get(symbol).calculate(operand1, operand2);
}

希望它可能会有用,其他高级成员可以对此设计进行更多说明。

不需要静态初始值设定项。在使用Calculator之前注册第三方运营商:

// Code of 3rd party developer: 
public static void main(String[] args) { 
OperatorRegistry.register(new MultiplyOperator()); 
OperatorRegistry.register(new PowerOperator()); 
Calculator c = new Calculator(); 
System.out.println(c.eval("+", 3, 9)); 
System.out.println(c.eval("-", 13, 9)); 
System.out.println(c.eval("*", 3, 9)); 
System.out.println(c.eval("^", 13, 9)); 
} 

并让计算器本身注册默认运算符。

也许将静态OperatorRegistry.register(Operator)移动到Calculator更方便:

Calculator.registerOperator(Operator);

然后Calculator会变成:

public class Calculator { 
private static OperatorRegistry operatorRegistry = new OperatorRegistry(); 
// Register default operators 
static {
Calculator.operatorRegistry.register(new SubtractOperator());
Calculator.operatorRegistry.register(new AddOperator());
}
public static registerOperator(Operator operator) {  
// Delegate call to 'OperatorRegistry'
Calculator.operatorRegistry.register(operator); 
} 
public double eval(String symbol, double operand1, double operand2) { 
return Calculator.operatorRegistry.get(symbol).calculate(operand1, operand2); 
}
}
// Code of 3rd party developer: 
public static void main(String[] args) { 
Calculator.registerOperator(new MultiplyOperator()); 
Calculator.registerOperator(new PowerOperator()); 
Calculator c = new Calculator(); 
System.out.println(c.eval("+", 3, 9)); 
System.out.println(c.eval("-", 13, 9)); 
System.out.println(c.eval("*", 3, 9)); 
System.out.println(c.eval("^", 13, 9)); 
} 

最新更新