簡體   English   中英

如何使用不共享同一父類的兩個幾乎相同的類?

[英]How to use two near-identical classes that do not share the same parent class?

我有2個幾乎完全相同的類,理想情況下應該共享相同的父類,但不要 (因為它們來自不同的庫,其源代碼我無法更改)。

為了舉例說明,我有兩個類,如:

public class Cat {
    public void speak() {
        System.out.println("Meow");
    }

    public CatFood findFood() {
        return new CatFood();
    }

    public void eat(CatFood food) {
        System.out.println("[Cat] Yum yum");
    }
}

public class Dog {
    public void speak() {
        System.out.println("Woof");
    }

    public DogFood findFood() {
        return new DogFood();
    }

    public void eat(DogFood food) {
        System.out.println("[Dog] Yum yum");
    }
}

現在理想情況下我想做的事情如下:

Animal[] animals = {new Cat(), new Dog()};
for (Animal animal : animals) {
    animal.speak();
    animal.eat(animal.findFood());
}

CatDog不繼承Animal ,我無法改變自己的源代碼。 我還想避免依賴instanceof作為拐杖:

for (Object animal : animals) {

    if (animal instanceof Dog) {
        Dog dog = (Dog) animal;
        dog.speak();
        dog.eat(dog.findFood());

    } else if (animal instanceof Cat) {
        Cat cat = (Cat) animal;
        cat.speak();
        cat.eat(cat.findFood());

    } else if (animal instanceof Rabbit) { // etc etc
}

代碼只重復了幾十萬次,所以如果我對邏輯進行一些小改動,我也必須復制和粘貼數十億次。

那么如何以最少的代碼重復使用這些類呢?

您可以使用適配器模式,但是您需要為每種類型的動物實現具體的適配器:

interface Animal {
    void speak();
    void eat();
}

class DogAdapter implements Animal {
    private Dog dog;

    public DogAdapter(Dog dog) {
        this.dog = dog;
    }

    public void speak() {
        dog.speak();
    }

    public void eat() {
        dog.eat(dog.findFood());
    }
}

class CatAdapter implements Animal {
    private Cat cat;

    public CatAdapter(Cat cat) {
        this.cat = cat;
    }

    public void speak() {
        cat.speak();
    }

    public void eat() {
        cat.eat(cat.findFood());
    }
}

使用工廠可能會封裝具體的創建:

class AnimalFactory {
    public static Animal createAdapter(Dog dog) {
        return new DogAdapter(dog);
    }

    public static Animal createAdapter(Cat cat) {
        return new CatAdapter(cat);
    }
}

然后你可以使用適配器並在循環中運行:

Animal[] animals = {AnimalFactory.createAdapter(cat), AnimalFactory.createAdapter(dog)};

for (Animal animal : animals) {
    animal.speak();
    animal.eat();
} 

一個痛點是eat()方法,因為DogFood,CatFood,...也沒有常見的超類型。

如果您無法修改這些類,並且希望將代碼保持在最小值,則可以使用反射來調用這些方法。 就像是:

Method method = obj.getClass().getMethod("speak");
method.invoke(obj);

但是考慮只使用反射作為最后的手段

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM