Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/373.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 以特定类型的方式处理子类的正确模式是什么?_Java_Design Patterns_Subclass - Fatal编程技术网

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());
    }

}