我有一个小的层次结构,它们都实现了一个公共接口。
每个具体类都需要接收一个包含例如公共字段的设置结构。问题是设置结构
我想知道你是否有任何优雅的设计来处理这个问题。我想构建类似的东西:
BaseFunc doer = new ConcreteImplementation1();
使用ConcreteImplementation1实现BaseFunc。并且有像
这样的东西doer.setSettings(settings)
但是''settings''对象具有适合ConcreteImplementation1的具体实现。
你会怎么做?
答案 0 :(得分:2)
这可能是一个命名的设计模式,如果是,我不知道名字。 声明一个实现所需接口的抽象类。抽象类构造函数应该采用您的设置对象的实例,从中提取全局设置。从抽象类派生一个或多个类。派生类构造函数应该获取设置对象的实例,将其传递给父类构造函数,然后提取任何本地设置。
以下是一个例子:
class AbstractThing implements DesiredInterface { private String globalSettingValue1; private String globalSettingValue2; protected AbstractThing(Settings settings) { globalSettingValue1 = settings.getGlobalSettingsValue1(); globalSettingValue2 = settings.getGlobalSettingsValue2(); } protected String getGlobalSettingValue1() { return globalSettingValue1; } protected String getGlobalSettingValue2() { return globalSettingValue2; } } class DerivedThing extends AbstractThing { private String derivedThingSettingValue1; private String derivedThingSettingValue2; public DerivedThing(Settings settings) { super(settings); derivedThingSettingValue1 = settings.getDerivedThingSettingsValue1(); derivedThingSettingValue2 = settings.getDerivedThingSettingsValue2(); } }
答案 1 :(得分:1)
听起来你需要一个非常标准的Visitor pattern。
简单地说,假设您的所有属性都存储为地图中的键值对。并且您的层次结构中有3个类:A,B,C。它们都实现了一些通用接口CI。
然后你需要创建一个这样的属性持有者:
public class PropertyHolder {
public Map<String, String> getCommonProperties () { ... }
public Map<String, String> getSpecialPropertiesFor (CI a) { return EMPTY_MAP; }
public Map<String, String> getSpecialPropertiesFor (A a) { ... }
public Map<String, String> getSpecialPropertiesFor (B b) { ... }
...
}
所有类都应该实现在接口CI中声明的1个方法getSpecialProperties
。实现简单如下:
public Map<String, String> getSpecialProperties (PropertyHolder holder) {
return holder.getSpecialPropertiesFor (this);
}
答案 2 :(得分:1)
具有匹配的设置对象层次结构,使用Factory创建与特定类匹配的设置。
答案 3 :(得分:0)
我沿着这条路走了一次。它起作用了,但在决定之后它不值得。
您可以定义基类MyBean或其他东西,它有自己的mergeSettings方法。您希望使用此框架的每个类都可以扩展MyBean,并为调用超类mergeSettings的mergeSettings提供自己的实现。这样,公共字段可以在超类上。如果你想得到真正的幻想,你可以定义和接口和抽象类,以真正使它漂亮。虽然你在它,也许你可以使用反射。无论如何,mergeSettings将采用一个Map,其中键是属性名称。每个类都有与常量相关的常量。
class MyBean extends AbstractMyBean ... {
public static final String FIELD1 = 'field1'
private String field1
public mergeSettings(Map<String, Object> incoming) {
this.field1 = incoming.get(FIELD1);
// and so on, also do validation here....maybe put it on the abstract class
}
}
虽然它为安装者做了很多工作......
答案 4 :(得分:0)
我开始玩一种新模式,我称之为“类型安全对象映射”。它就像一个Java Map,但值有类型。这允许您定义每个类想要读取的键,并以类型安全的方式获取值(没有运行时成本!)
关于这一点的好处是它仍然是一张地图,因此您可以轻松实现继承,通知等。
答案 5 :(得分:0)
您可以使用Generics定义此实例所需的设置类型。像这样:
public abstract class MySuperClass<T extends MySettingsGenericType>{
public MySuperClass(T settings){
//get your generic params here
}
}
public class MyEspecificClass extends MySuperClass<T extends MySettingsForThisType>{
public MySuperClass(T settings){
super(settings);
//Get your espefic params here.
}
}
//and you could use this
BaseFunc doer = new ConcreteImplementation1(ConcreteSettingsFor1);
//我不编译这段代码并急着写。对不起,如果有一些错误...