请考虑以下情况:
Caracteristic
的抽象类,它可以具有名称和级别。它还会覆盖Object.toString()
。Caracteristic
的子代,分别是CaracteristicA
,CaracteristicB
和CaracteristicC
,这些子代覆盖了名称(并可能覆盖级别)。Statistic
的抽象类,它具有2个抽象函数:int getValue()
和一个Object.toString()
覆盖。StatisticA
的类,它扩展了Statistic
,其中被覆盖的int getValue()
的结果取决于所需的CaracteristicA
和CaracteristicB
实例。我有一个名为StatisticB
的相似类,但是int getValue()
的结果取决于所需的CaracteristicC
实例。所有子项也会覆盖Statistic.toString()
。为客户创建统计信息时,我做的事情很丑陋,这是这样的:
CaracteristicA caracteristicA = null;
CaracteristicB caracteristicB = null;
CaracteristicC caracteristicC = null;
for (Caracteristic currentCaracteristic : listOfCaracteristics) {
if (currentCaracteristic instanceof CaracteristicA) {
caracteristicA = (CaracteristicA)currentCaracteristic;
} if (currentCaracteristic instanceof CaracteristicB) {
caracteristicB = (CaracteristicB)currentCaracteristic;
} if (currentCaracteristic instanceof CaracteristicA) {
caracteristicC = (CaracteristicC)currentCaracteristic;
} else {
throw new IllegalArgumentException("Unknown caracteristic !");
}
}
// "client.addStatistic" expects a "Statistic".
// "StatisticA"'s constructor expects an instance of "caracteristicA" and "caracteristicB".
// "StatisticB"'s constructor expects an instance of "caractersiticC".
client.addStatistic(new StatisticA(caracteristicA, caracteristicB));
client.addStatistic(new StatisticB(caracteristicC));
问题:如果我想添加一个依赖于StatisticC
的{{1}}和一个新子集CaracteristicA
(我们将其命名为{{1} }),我需要添加一个变量来存储适当的特征,在循环中添加另一个Caracteristic
来找到它,然后我终于能够使用适当的特征来创建所需的统计信息。
我相当确定我可以把整个事情搞得一团糟,我想知道我该怎么做。在Google上搜索和Stack Overflow似乎使我指向了“ 工厂”和“ 访客”设计模式,但我不确定它们是否会对我有所帮助或使情况更糟
我还尝试向CaracteristicD
添加一个else if
抽象方法,使孩子们可以用其类型覆盖它(例如:Object getType()
),但是我意识到,如果我事先知道,这种方法就可以工作Caracteristic
的哪个子代正在迭代。
更新:通过执行CaracteristicA getType()
,listOfCaracteristics
等来填充listOfCaracteristics
。这是抽象类listOfCaracteristics.add(new CaracteristicA());
的代码:
listOfCaracteristics.add(new CaracteristicB());
这是其中一个孩子(Caracteristic
)的代码:
abstract class Caracteristic {
private final String name;
private int level;
Caracteristique(String name, int level) {
this.name = name;
this.level = level;
}
public int getLevel() {
return this.level;
}
@Override
public String toString() {
return this.name;
}
}
答案 0 :(得分:1)
与其为每个Caracteristic
创建一个实例并将它们放入列表中以随后分解列表并将它们分配给变量,而是使用正确的Caracteristic
实例化变量。这样可以大大简化代码:
CaracteristicA caracteristicA = new CaracteristicA();
CaracteristicB caracteristicB = new CaracteristicB();
CaracteristicC caracteristicC = new CaracteristicC();
CaracteristicD caracteristicD = new CaracteristicD(); //hypothetic
client.addStatistic(new StatisticA(caracteristicA, caracteristicB));
client.addStatistic(new StatisticB(caracteristicC));
client.addStatistic(new StatisticC(caracteristicA, caracteristicD)); //hypothetic
我还要添加更多内容。 Caracteristic
是抽象类但没有成员抽象的事实表明设计不好。最后,我怀疑您唯一需要做的就是控制Statistic
中允许使用一对值(名称和级别)。
然后,可以简化整个Caracteristic
的层次结构
public enum Caracteristic {
A("Hello World!", 1), B("easy", 2), C("medium", 3), D("hard", 4);
private final String name;
private final int level;
Caracteristic(String name, int level)
{
this.name = name;
this.level = level;
}
@Override
public String toString() { return name; }
public int getLevel() { return level; }
}
使用以下类似的代码再次简化您的代码:
client.addStatistic(new StatisticA(Caracteristic.A, Caracteristic.B));
client.addStatistic(new StatisticB(Caracteristic.C));
client.addStatistic(new StatisticC(Caracteristic.A, Caracteristic.D)); //hypothetic
现在,使用Caracteristic
作为构造函数参数确实没有任何好处,因为仅存在Caracteristic.A
的一个实例,因此可以在StatisticX
内部直接使用它们!
再一个简化的版本将变成:
client.addStatistic(new StatisticA());
client.addStatistic(new StatisticB());
client.addStatistic(new StatisticC()); //hypothetic
例如,使用StatisticA
蜜蜂
public final class StatisticA {
public void DoSomeWork() {
int differenceLevel = Caracteristic.B.getLevel() - Caracteristic.A.getLevel();
string bothLevels = Caracteristic.A.toString() + " " + Caracteristic.B.toString();
System.out.PrintLn(bothLevels + ": " + differenceLevel);
}
}
要进一步迈出一步,我将假设每个Statistic
都执行“相同”的工作(除了使用不同的特性)。这将允许将其重构为一个单一的类Statistic
public final class Statistic {
private final Iterable<Integer> caracs;
public Statistic(Caracteristic... caracs) {
this.caracs = Arrays.asList(caracs);
}
public void DoSomeWork() {
System.out.PrintLn(caracs.stream()
.map(Caracteristic::toString)
.Collect(Collectors.joining(",")));
System.out.PrintLn(caracs.stream()
.map(Caracteristic::getLevel)
.sum());
}
}
随着用法的使用(最终简化代码)
client.addStatistic(new Statistic(Caracteristic.A, Caracteristic.B));
client.addStatistic(new Statistic(Caracteristic.C));
client.addStatistic(new Statistic(Caracteristic.A, Caracteristic.D)); //hypothetic
开始时会有:
具有所有简化功能:
答案 1 :(得分:0)
也许我错了,因为我不太确定是否理解这个问题,但是为什么不使用Composite Pattern来表示Carateristic
的层次结构呢?
这样,您将能够创建新的Composite
特性(例如CaracteristicAB
)并将其传递给需要多个Statistic
的{{1}}。