gpt4 book ai didi

java - 以类型特定的方式处理子类的正确模式是什么?

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:22:24 24 4
gpt4 key购买 nike

我有一组 Animal 对象。

我的核心代码希望将所有这些都视为动物,都一样。每个 Animal 都需要以某种方式进行处理。处理的性质取决于动物的亚型(鸟类、哺乳动物等)。

我的代码目前如下所示。

public interface Animal {
public String getTaxonomyClass();
}

public abstract class Bird implements Animal {

@Override
public String getTaxonomyClass() {
return "aves";
}

// Specific to birds
public abstract float getWingspan();

}

public abstract class Mammal implements Animal {

@Override
public String getTaxonomyClass() {
return "mammalia";
}

// Specific to mammals
public abstract int getToothCount();

}

public interface AnimalProcessor {
public String getSupportedTaxonomyClass();
public void process(Animal a);
}

public class MammalProcessor implements AnimalProcessor {

@Override
public String getSupportedTaxonomyClass() {
return "mammalia";
}

@Override
public void process(Animal a) {
System.out.println("Tooth count is " + ((Mammal)a).getToothCount());
}

}

public class BirdProcessor implements AnimalProcessor {

@Override
public String getSupportedTaxonomyClass() {
return "aves";
}

@Override
public void process(Animal a) {
System.out.print("Wingspan is " + ((Bird)a).getWingspan());
}

}

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ZooKeeper {

Map<String, AnimalProcessor> registry = new HashMap<String, AnimalProcessor>();

public void registerProcessor(AnimalProcessor ap)
{
registry.put(ap.getSupportedTaxonomyClass(), ap);
}

public void processNewAnimals(List<Animal> newcomers)
{
for(Animal critter : newcomers)
{
String taxonomy = critter.getTaxonomyClass();
if(registry.containsKey(taxonomy))
{
// if I can process the animal, I will
AnimalProcessor ap = registry.get(taxonomy);
ap.process(critter);
}

}
}
}

import java.util.LinkedList;
import java.util.List;

public class MainClass {

public static void main(String[] args) {

ZooKeeper keeper = new ZooKeeper();
keeper.registerProcessor(new MammalProcessor());
keeper.registerProcessor(new BirdProcessor());

List<Animal> animals = new LinkedList<Animal>();

animals.add(new Mammal() { // badger

@Override
public int getToothCount() {
return 40;
} }
);

animals.add(new Bird() { // condor

@Override
public float getWingspan() {
return 2.9f;
} }
);

keeper.processNewAnimals(animals);

}
}

通常这很容易理解并且效果很好!我可以在闲暇时添加插件新处理器和动物类型,而无需更改 ZooKeeper 类或任何接口(interface)。您可以想象一个更高级的主类,从数据库中加载 Animals,然后依次处理它们。

但是,我担心 AnimalProcessor 子类中的向下转换!这让我觉得不应该存在,并且可能违反 OO 原则。毕竟,目前我可以将 Bird 传递给 MammalProcessor 的 process() 方法,并且会出现 ClassCastException。

谁能提出一个设计模式来解决这个问题?我查看了访问者模式,但不太明白如何在这种情况下应用它!关键是让核心代码 (ZooKeeper) 对所有动物一视同仁,这样就可以轻松添加对新动物的支持。谢谢!

最佳答案

我建议如下:

public interface Animal {
public AnimalProcessor<? extends Animal> getProcessor();
}

因此每只动物都会返回与其匹配的处理器。

public interface AnimalProcessor<T extends Animal> {
public void process(T a);
}

因此,处理器将使用其应该处理的匹配类型进行键入。所以植入将是这样的:

public abstract class Bird implements Animal {
private BirdProcessor processor = new BirdProcessor();
public abstract float getWingspan();
@Override
public AnimalProcessor<Bird> getProcessor() {
return processor;
}
}

public class BirdProcessor implements AnimalProcessor<Bird> {
@Override
public void process(Bird b) {
System.out.print("Wingspan is " + b.getWingspan());
}
}

关于java - 以类型特定的方式处理子类的正确模式是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10534756/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com