没有方法与字段

时间:2017-05-23 09:52:49

标签: java oop design-patterns

我有两个类,LivingCreatureAnimal继承自它。

我想为每个现有的Animal实现一个类,但由于不同的动物共享许多功能,我希望能够将动物分为几类: 飞行,散步,游泳,食肉动物,素食等...

每只动物都可以居住在几个地方,甚至是同一个地区,例如飞行,散步和食肉动物。

此外,每个类别可能包含几个独特的属性,例如飞行动物应该包括速度和进食类型(例如,它是否坐在树上采摘蠕虫,或“袭击”地球并用它的腿采摘动物)

我绝对要避免的第一件事是为每个具体的动物实施保留一组不同的字段。

现在,由于某些类别只是二元(Carnivore或Vegan)而有些类别绝对不是,我想知道实现它的正确方法是什么。

我倾向于选择每个类别的接口,即使他们不会持有任何方法,但我遇到了冲突:

  • 持有一个像isMeatEating这样简单用途的接口看起来很奇怪,它包含一个布尔字段。
  • 另一方面,将几个类别作为Animal的字段,将其他几个类别实现为Interfaces,听起来非常错误和令人困惑。

这里设计正确/最佳选择是什么? (也许有一个 符合此用例的设计模式)

1 个答案:

答案 0 :(得分:0)

您似乎描述的模式是traitmixin的模式。

  

Mixins是一种语言概念,允许程序员将一些代码注入到类中。 Mixin编程是一种软件开发方式,其中功能单元在类中创建,然后与其他类混合使用。

某些语言(如Scala)有built-in support for these concepts

在Java 8中,在默认方法的帮助下,we can do traits在某种程度上,我这样说,因为这是not the reason为什么设计默认方法。

现在,如果没有详细说明你正在做的事情,很难就你的设计提出建议,但我会尝试举例说明我是如何看待它的。

让我们专注于饮食概况:食肉动物与食草动物。食肉动物吃其他动物,食草动物吃植物或植物来源的东西,杂食动物可以吃两者。动物和植物都是可食用的材料。

interface Edible {
   Collection<Nutrients> getNutrients();
}

interface Vegetal extends Edible {}
interface Animal extends Edible{}

所有动物都吃,所以我们可以将动物定义为:

interface Animal<T extends Edible> extends Edible {

    Stomach getStomach();
    Collection<Bolus> masticate(T food);

    default void eat(T food) {
        Objects.requiresNonNull(food, "The food must not be null");
        for(Bolus bolus : this.masticate(food)) {
            this.getStomach().ingest(bolus);
        }
    }
}

告诉我StomachBolus的详细信息,让我们假设所有的动物都有胃,可以咀嚼食物,将其变成大丸剂并将其摄入胃中。 / p>

现在,我们终于可以达到我们的定义:

interface Carnivore extends Animal<Animal> { }
interface Herbivore extends Animal<Vegetal> { }
interface Omnivore extends Animal<Edible> { }

现在你可以定义一个

class Chicken implements Herbivore {}
class Lion implements Carnivore {}
class Bear implements Omnivore {}

现在,Chicken只能使用Vegetal类型的内容,Lion只能使用Animal类型的内容,而Bear只能吃Edibleimport requests, bs4, csv, json from pprint import pprint with open('playerslist.json') as data_file: data = json.load(data_file) for i in data['player']: name = i['player_name'] url = 'https://www.capfriendly.com/players/'+name r = requests.get(url) soup = bs4.BeautifulSoup(r.text, 'lxml') table = soup.find(id="cont_x") with open(name+".csv", "w", newline='') as team_data: def parse_td(td): filtered_data = [tag.text for tag in td.find_all('span', recursive=False) if 'q' not in tag.attrs['class']] return filtered_data[0] if filtered_data else td.text; for tr in table('tr', class_=['column_head', 'odd', 'even']): row = [parse_td(td) for td in tr('td')] writer = csv.writer(team_data) writer.writerow(row) 事情。

我对我的界面Animal的默认方法提供的细节越多,我在这些类中实现的细节就越少,或许是一种实现你想要的方法。

我知道我可能无法回答你的问题,但我希望我至少能给你一些关于你可以继续调查和试验理想解决方案的想法。