哪种设计模式以及如何使用OOP设计此场景

时间:2014-01-16 12:41:52

标签: java oop design-patterns

我在设计模块时遇到问题,任何人都可以帮助我吗?

因为很难维护这种模块,我也认为这可以测试我的设计模式使用技巧。

要求

这基本上是一个农业项目(网络应用程序)。我需要设计一个模块,进行一些计算。

玉米,番茄,秋葵等农作物有不同的作物。每种作物都有不同的特性。

每个特征的测量标度都是200-1000之间的整数。现在让我们说我已经种植了作物并完成了特征测量。现在我想做一些测量。有些测量很简单,有些很复杂。

实施例

让我们举一个作物玉米的例子。我记录了15个特征的观察结果。 (我们将使用trait1-trait15作为示例,实际名称可以像plt_ht,yld等。)

我记录了每个特征的5个观察结果:

trait1 trait2 trait3 trait5 trait6..... trait15
01,02,03,04 01,02,03,04 01,02,03,04

用户登录系统并选择他的庄稼并输入这些观察的数据。我必须计算为每个特征输入的数据的平均值或总和。

问题的复杂性/中心

到目前为止它很简单但复杂性来自于我对某些特征有一些不同的公式。

示例:trait YLD有一个公式,我必须根据该公式计算其值,这也可能取决于其他一些特征。每种不同的作物都有不同的特性。

所有这一切我都能做到 - 每当用户选择裁剪时,我会检查那些特定的特征并进行计算(如果它不是特殊的特性,那么我要根据数据库条目对其进行平均或求和),但是有一个很多硬编码。 我想就更好的处理方法提出建议。

我的代码需要处理简单和复杂的计算。 简单的计算很简单,我已经为特征输入了平均值。 当我不得不进行复杂的计算时,问题出现了,因为每个作物都有不同的特征和它们自己的公式,所以要计算我必须检查作物然后检查复杂的特性。所以我必须硬编码复杂特征的特征名称。 可以告诉我如何使用Java oops [?!?]来设计它,以便我可以使它通用吗?

我有大约10种不同的作物。有些计算特定于作物,因此会有很多代码,例如下面的代码:

hasZeroValue = (HashMap<String, ArrayList<String>>) dataValues[1];
} else if(cropId.equalsIgnoreCase("TO") && traitName.equalsIgnoreCase("TLSSG_70")) {
    traitAvg=calculateTLCV(traitName, traitAvg,dataPoint, dataTraits, hybrid, repl, traitValues, dataPvalues,50);
} else if(cropId.equalsIgnoreCase("TO") && traitName.equalsIgnoreCase("TLSSG_100")) {
    traitAvg=calculateTLCV(traitName, traitAvg,dataPoint, dataTraits, hybrid, repl, traitValues, dataPvalues,50);
} else if(cropId.equalsIgnoreCase("TO") && traitName.equalsIgnoreCase("YVMV_60")) {
    traitAvg=tomatoYVMVCalculation(traitName, traitAvg,dataPoint, dataTraits, hybrid, repl, traitValues, dataPvalues);
} else if(cropId.equalsIgnoreCase("TO") && traitName.equalsIgnoreCase("YVMV_90")) {
    traitAvg=tomatoYVMVCalculation(traitName, traitAvg,dataPoint, dataTraits, hybrid, repl, traitValues, dataPvalues);
} else if(cropId.equalsIgnoreCase("TO") && traitName.equalsIgnoreCase("YVMV_120")) {
    traitAvg=tomatoYVMVCalculation(traitName, traitAvg,dataPoint, dataTraits, hybrid, repl, traitValues, dataPvalues);
} else if(cropId.equalsIgnoreCase("TO") && traitName.equalsIgnoreCase("ELCV_60")) {
    traitAvg=tomatoYVMVCalculation(traitName, traitAvg,dataPoint, dataTraits, hybrid, repl, traitValues, dataPvalues);
} else if(cropId.equalsIgnoreCase("TO") && traitName.equalsIgnoreCase("ELCV_90")) {
    traitAvg=tomatoYVMVCalculation(traitName, traitAvg,dataPoint, dataTraits, hybrid, repl, traitValues, dataPvalues);
} else if(cropId.equalsIgnoreCase("TO") && traitName.equalsIgnoreCase("ELCV_120")) {
    traitAvg=tomatoYVMVCalculation(traitName, traitAvg,dataPoint, dataTraits, hybrid, repl, traitValues, dataPvalues);
} else if(cropId.equalsIgnoreCase("OK") && traitName.equalsIgnoreCase("YVMV_60")) {
    traitAvg=tomatoYVMVCalculation(traitName, traitAvg,dataPoint, dataTraits, hybrid, repl, traitValues, dataPvalues);
} else if(cropId.equalsIgnoreCase("OK") && traitName.equalsIgnoreCase("YVMV_90")) {
    traitAvg=tomatoYVMVCalculation(traitName, traitAvg,dataPoint, dataTraits, hybrid, repl, traitValues, dataPvalues);
} else if(cropId.equalsIgnoreCase("OK") && traitName.equalsIgnoreCase("YVMV_120")) {
    traitAvg=tomatoYVMVCalculation(traitName, traitAvg, dataPoint, dataTraits, hybrid, repl, traitValues, dataPvalues);
} else if(cropId.equalsIgnoreCase("OK") && traitName.equalsIgnoreCase("ELCV_60")) {

每个作物应该写一个类,把它看作是支持109种作物的应用,现在每个用户都登录到系统,我有链接他可以做上面的练习,作物是一类更好。有可能每个作物的100个性状也应该是每个特性。请告诉我。

3 个答案:

答案 0 :(得分:2)

将特征和作物封装到单独的类中首先你可能想要创建一些抽象类,如 Crop.class Trait.class ,它们将包含基本骨架和所有作物或性状的共同点,之后你可以扩展这些类并为每个特定的作物或性状制作一个单独的类,这样特定的类将包含特定于该作物或性状的信息和过程,并仍然保持Crop.class和Trait.class的一般功能。

您还可以为需要对特征执行的单个操作或操作集创建类似的模式。

这里的想法是以更易于维护的方式展开它,这将使添加更多的作物和特性或修改现有的作物变得轻而易举。


编辑:

如果您有任意数量的作物/性状,那么每种作物单独写一个类似乎不是解决方案。作物的个性将来自更普遍的阶级的某些属性和状态。

然而,如果一些作物/性状具有相似/相同的功能/特性(我认为它们会提到大约100种作物/性状等),你可以将它们分组在一个单独的类别中。 ( GrainCrop.class 或其他内容)

这意味着您仍然希望获得 Crop.class Trait.class 摘要,而不是将每个裁剪分组到一个单独的类中例如,在类似作物的包装中分组,这样您就可以轻松访问或限制作物的某个子集范围。

此外,您仍然可以简化某些任务,因此它们看起来不那么笨重,甚至可能将它们分散在不同的类中。

根据您的示例,如果我们分析它,我们可以看到最重复的属性是裁剪ID(cropId.equalsIgnoreCase("OK")cropId.equalsIgnoreCase("TO")

因此,无需多次检查裁剪ID是“TO”还是“OK”,您可以检查一次并有两个单独的分支来检查“TO”属性和“OK”属性。

此外,如果某些作物可能具有相同的常用操作集,那么您可以将它们分组在 BasicCropOperations.class 下,然后将其余的复杂操作划分为类似的行为集,如 EnvironmentalCropOperations.class 或者某些东西,例如有热量和湿度等因素。

这个想法仍然是相同的,将所有内容划分为更小的模块。 (例如:为不同的作物/特性写200个课程是不合理的)

答案 1 :(得分:0)

对此的整体解决方案取决于您没有告诉我们的细节。我们不知道您是否希望为复杂计算编写代码,这意味着您可以为每个裁剪创建一个类,或者您是否希望能够添加裁剪或更改计算而无需更改代码。

然而,你正在做的一些事情可以立即得到改善。您的if a && b then x else if a && c then y else if a && d等模式可以更改为:

if a
{
  if b { x }
  else if c { y }

...
}

更重要的是,假设您可以为作物和/或计算创建类,您可以存储此类对象的集合并使用它们来替换if / then / else序列。例如:创建一个由上面的'traitName'值索引的对象的hashmap;而不是if / then / else,使用HashMap.get()获取对相应对象的引用,并将计算方法放在该对象中。

我想你可以称之为这些设计模式,但这并不是这个术语的通常含义。

答案 2 :(得分:0)

关于这被视为无聊答案或根本没有回答的风险...... 不要使用Java,使用Scala或像Ruby这样的动态语言。你甚至在Scala中使用了正确的名称:“特质”。

设计模式可能很有用,但是一旦它们不是为了方便而使用,而是为了解决语言是否适合解决问题的严重缺陷,我认为是时候跳过技术了。