我有一个名为Base
的抽象类,它处理一堆逻辑来处理我的一些数据。 API看起来像这样:
// Class has no abstract methods, but is uninstantiable
public abstract class Base {
private Param param;
protected Base() {}
protected void setParam(Param param) {
this.param = param
}
public void doThing() {
// Code here to do a common thing
}
public void doOtherThing() {
// Code here to do another common thing
}
protected void handle(Object... objects) {
// This code delegates work to a scripting language via the param
// It is not type safe and the array of objects needed will vary depending
// on the implementing class.
}
}
当然,这里奇怪的是handle(Objects...)
方法。要显示它的使用方式,请查看其中一个子类:
public class Person extends Base {
protected Person(Param param) {
super();
setParam(param);
}
public void handle(String name, int age) {
// Expose a type safe interface to the world
super.handle(name, age);
}
}
正如您所看到的,子类隐藏了super.handle
,这是受保护的,对于某些参数,以便此类的使用者可以具有类型安全交互,而无需传递对象数组。问题是,我想从一个工厂创建这些,这个工厂强制每个参数有一个子类实例。目前,这家工厂看起来像这样:
public class Factory {
Map<Param, Person> persons;
Map<Param, Other> others; // Other also extends Base
public Person getPerson(Param param) {
Person person = persons.get(param);
if (person == null) {
person = new Person(param);
persons.put(param, person);
}
return person;
}
public Other getOther(Param param) {
Other other = others.get(param);
if (other == null) {
other = new Other(param);
other.put(param, other);
}
return other;
}
}
显然,这很糟糕,但我认为没有更好的方法来处理这种情况,因为通过param与脚本语言交互的奇怪性质,它依赖于字符串构造来执行代码。有没有人对如何清理这个设计有任何指导?
答案 0 :(得分:1)
可以概括工厂类,使用一些泛型和反射来在运行时实例化特定的子类类型:
import java.util.HashMap;
import java.util.Map;
public class Factory<T> {
private Map<Param, T> instances = new HashMap<Param, T>();
public final T create(Class<T> clazz, Param param) throws Exception {
T cur = instances.get(param);
if (cur == null) {
cur = clazz.newInstance();
((Base)cur).setParam(param);
instances.put(param, cur);
}
return cur;
}
}
子类应该有no-args构造函数,而不是public;为了一致性,删除with-param one:
public class Person extends Base {
protected Person(){}
public void handle(String name, int age) {
// Expose a type safe interface to the world
super.handle(name, age);
}
}
使用示例:
public class TestFactory {
public static void main(String[] args) throws Exception {
Factory<Person> factory = new Factory<Person>();
Person p = factory.create(Person.class, new Param());
}
}
当然我知道这不是一个模式,它不是我可以引以为豪的更优雅的代码,但仍然避免你必须为每个新的子类更改工厂,它不使用静态方法并保持在单点指向缓存逻辑。