Java 以特定类型的方式处理子类的正确模式是什么?
我收集了一些动物物品 我的核心代码希望将所有这些都视为动物,一视同仁。每种动物都需要以某种方式进行加工。加工的性质取决于动物的子类型(鸟类、哺乳动物等) 我的代码目前如下所示Java 以特定类型的方式处理子类的正确模式是什么?,java,design-patterns,subclass,Java,Design Patterns,Subclass,我收集了一些动物物品 我的核心代码希望将所有这些都视为动物,一视同仁。每种动物都需要以某种方式进行加工。加工的性质取决于动物的子类型(鸟类、哺乳动物等) 我的代码目前如下所示 public interface Animal { public String getTaxonomyClass(); } import java.util.HashMap; 导入java.util.List; 导入java.util.Map; 公营动物园管理员{ Map registry=newh
public interface Animal {
public String getTaxonomyClass();
}
import java.util.HashMap;
导入java.util.List;
导入java.util.Map;
公营动物园管理员{
Map registry=newhashmap();
公共无效注册表处理器(AnimalProcessor ap)
{
registry.put(ap.getSupportedTaxonomyClass(),ap);
}
新动物(列出新来者)
{
用于(动物生物:新来者)
{
字符串分类法=critter.getTaxonomyClass();
if(registry.containsKey(分类法))
{
//如果我能处理这个动物,我会的
AnimalProcessor ap=registry.get(分类法);
ap.过程(critter);
}
}
}
}
import java.util.LinkedList;
导入java.util.List;
公共类主类{
公共静态void main(字符串[]args){
ZooKeeper=新的ZooKeeper();
keeper.registerProcessor(新处理器());
keeper.registerProcessor(新的BirdProcessor());
列出动物=新建链接列表();
动物。添加(新哺乳动物(){//獾
@凌驾
public int getToothCount(){
返回40;
} }
);
添加(新鸟(){//condor
@凌驾
公共浮标getWingspan(){
返回2.9f;
} }
);
饲养动物(动物);
}
}
一般来说,这很容易理解,而且效果很好!我可以随意添加插件式新处理器和动物类型,而无需更改ZooKeeper类或任何接口。您可以想象一个更高级的主类,从数据库加载动物,然后依次处理它们
然而,我担心AnimalProcessor子类内部的降级!这在我看来是不应该存在的,可能违反了OO原则。毕竟,现在我可以将一只鸟传递给处理器的process()方法,并且会有一个ClassCastException
有人能提出一种设计模式来解决这个问题吗?我查看了访问者模式,但不太明白如何在这种情况下应用它!关键是要使核心代码(ZooKeeper)对所有动物一视同仁,这样就可以轻松添加对新动物的支持。谢谢 所以你有这样一门课
public abstract class Bird implements Animal {
@Override
public String getTaxonomyClass() {
return "aves";
}
// Specific to birds
public abstract float getWingspan();
}
public class Bird implements Animal {
float wingspan = 0.0f;
public Bird(float wingspan){
this.wingspan = wingspan;
}
@Override
public String getTaxonomyClass() {
return "aves";
}
// Specific to birds
public float getWingspan(){
return wingspan;
}
}
public void process() {
System.out.print("Wingspan is " + getWingspan());
}
所有鸟类
都会有翼展,即使翼展为0
。那么,你为什么不把课堂改成这样
public abstract class Bird implements Animal {
@Override
public String getTaxonomyClass() {
return "aves";
}
// Specific to birds
public abstract float getWingspan();
}
public class Bird implements Animal {
float wingspan = 0.0f;
public Bird(float wingspan){
this.wingspan = wingspan;
}
@Override
public String getTaxonomyClass() {
return "aves";
}
// Specific to birds
public float getWingspan(){
return wingspan;
}
}
public void process() {
System.out.print("Wingspan is " + getWingspan());
}
因此,要创建一只新的鸟
,而不是这样做
animals.add(new Bird() { // condor
@Override
public float getWingspan() {
return 2.9f;
} }
);
你会这么做的
animals.add(new Bird(2.9f)); // condor
这似乎会使整个事情变得更加简单和美好。你也可以对你的哺乳动物类做类似的改变
现在,对于动物的加工。。。如果要处理所有的动物
,您可以在Bird
中实现process()
,而不需要单独的BirdProcessor
类。为此,在Animal
中声明一个方法public void process()代码>。你的Bird
会像这样实现它
public abstract class Bird implements Animal {
@Override
public String getTaxonomyClass() {
return "aves";
}
// Specific to birds
public abstract float getWingspan();
}
public class Bird implements Animal {
float wingspan = 0.0f;
public Bird(float wingspan){
this.wingspan = wingspan;
}
@Override
public String getTaxonomyClass() {
return "aves";
}
// Specific to birds
public float getWingspan(){
return wingspan;
}
}
public void process() {
System.out.print("Wingspan is " + getWingspan());
}
您可以将AnimalProcessor
更改为只需执行此操作(注意:不再是接口)
然后,您的AnimalProcessor
类将能够处理所有动物
或者,如果您想保持AnimalProcessor
的原样,最好更改以下内容,以避免类异常
(这里的代码是针对BirdProcessor
)
这就是你想要的吗?我建议如下:
public interface Animal {
public String getTaxonomyClass();
public void process();
}
现在,实现animal的每个animal类都应该实现自己的处理逻辑。
例如:
public class Bird implements Animal {
public Bird(float wingSpan) {
this.wingSpan = wingSpan;
}
@Override
public String getTaxonomyClass() {
return "aves";
}
@Override
public void process() {
System.out.print("Wingspan is " + wingSpan);
}
// Specific to birds
private float wingspan;
}
现在您只能有一个AnimalProcessor,其处理方式如下:
public void process(Animal a) {
a.process();
}
你的问题是一些方法,比如
public abstract int getToothCount();
…在动物中没有定义。相反,它们是在动物的特定亚类中定义的。这意味着你不能笼统地对待动物,因为它们根本不同
要克服这一点,一种方法是为动物类中的所有这些对象创建抽象方法
Bird可能会用“0”响应getToothCount()
由于所有动物都可以响应getWingspan()、getTootCount()等,因此您不必执行任何特定于类型的检查。如果这还不够好,请在Animal中创建“boolean hasWings()”、“boolean Hasteth()”等的抽象实现
现在你可以说,对于某种动物a:
if (a.hasWings()) System.out.println("My wingspan is "+a.getWingSpan());
这对任何动物都适用。当然,动物的每个亚类都必须实现所有不同的方法
另一个选择是向Animal添加非抽象方法。这些方法将提供默认答案。例如,getWingSpan()将返回0,getToothCount()将返回0,等等。Shark将覆盖getToothCount()。Eagle将覆盖getWingSpan()
那么您的子类只需重写(甚至知道)与它们直接相关的方法。我建议如下:
public interface Animal {
public AnimalProcessor<? extends Animal> getProcessor();
}
公共界面动物{
公共动物处理器这是一个很好的工作场所
首先,需要将AnimalProcessor设置为通用:
public interface AnimalProcessor <T extends Animal> {
public String getSupportedTaxonomyClass();
public void process(T a);
}
公共接口动物处理器{
公共字符串getSupportedTaxonomyClass();
公共无效程序;
}
接下来,在特定的处理器中,指定泛型类型-例如哺乳动物:
public class MammalProcessor implements AnimalProcessor<Mammal> {
public String getSupportedTaxonomyClass() {
return "mammalia";
}
public void process(Mammal a) {
System.out.println("Tooth count is " + a.getToothCount());
}
}
public类处理器实现AnimalProcessor{
公共Stri
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());
}
}
public interface AnimalProcessor <T extends Animal> {
public String getSupportedTaxonomyClass();
public void process(T a);
}
public class MammalProcessor implements AnimalProcessor<Mammal> {
public String getSupportedTaxonomyClass() {
return "mammalia";
}
public void process(Mammal a) {
System.out.println("Tooth count is " + a.getToothCount());
}
}
public interface AnimalProcessor<T extends Animal> {
public String getSupportedTaxonomyClass();
public void process(T a);
}
public class MammalProcessor implements AnimalProcessor<Mammal> {
@Override
public String getSupportedTaxonomyClass() {
return "mammalia";
}
@Override
public void process(Mammal a) {
System.out.println("Tooth count is " + a.getToothCount());
}
}