Переопределение методов в шаблоне проектирования Decorator (Java) - PullRequest
2 голосов
/ 26 января 2020

У меня есть вопрос относительно шаблона проектирования Decorator.

У меня есть этот класс:

class SimpleShip<T extends Weapon> implements Comparable<SpaceShip>{

    private T weapon;
    private int points = 100;

    public SimpleShip(T weapon){
        this.weapon = weapon;
    }

    public int <D extends Weapon> compareTo(SpaceShip<?> other){
        return T.quality - D.quality;
    }

    public void attack(SpaceShip<?> other){
        other.gotHit(T.fire());
    }

    public void gotHit(int reduction){
        this.points -= reduction;
    }
}

Я хочу создать два типа космического корабля (две дополнительные функциональности) - оба отличаются реализации метода gotHit, я сделал это следующим образом:

abstract class ShipDecorator<T extends Weapon> extends SimpleShip<T>{

    private SimpleShip<T> simpleShip;

    public ShipDecorator(SimpleShip<T> simpleShip){
        this.simpleShip = simpleShip;
    }

    @Override
    public void attack(SpaceShip<?> other){
        simpleShip.attack();
    }

    @Override
    public int <D extends Weapon> compareTo(SpaceShip<?> other){
        return simpleShip.compareTo(other);
    }

    @Override
    public void gotHit(int reduction){
        simpleShip.gotHit(reduction);
    }
}

class GuardedShip<T extends Weapon> extends ShipDecorator<T>{
    public GuardedShip(SimpleShip<T> other, T weapon){
        super(other);
    }

    @Override
    private void gotHit(int reduction){
        simpleShip.gotHit(reduction);
        Random r = new Random();
        simpleShip.gotHit(r.nextInt(1,25));
    }
}

class SneakyShip<T extends Weapon> extends ShipDecorator<T>{
    public SneakyShip(SimpleShip<T> other, T weapon){
        super(other);
    }

    @Override
    private void gotHit(int reduction){
        if(new Random().nextDouble() > 0.25){
            simpleShip.gotHit(reduction);
        }
    }
}

Мой вопрос - должны ли все методы в API SimpleShip быть переопределены декоратором? Я думаю, что они должны, потому что вы должны делегировать запросы к сохраненному экземпляру SimpleShip, но школьное решение, которое мне было дано для этой проблемы, не отменяет его, и это сбивает меня с толку.

Ответы [ 2 ]

0 голосов
/ 26 января 2020

Я бы не сказал, что он должен переопределить методы SimpleShip, если он на самом деле ничего не делает в переопределенном методе и будет равен

@Override
public void method() {
  super.method();
}

тогда вы просто будете генерировать больше строк кода. Если вы хотите что-то украсить, то вам, очевидно, необходимо переопределить.

Для повторного использования вашего примера, хотя это немного странно:

class SneakyShip<T extends Weapon> extends ShipDecorator<T>{
    public SneakyShip(SimpleShip<T> other, T weapon){
        super(other);
    }

    // This is fine, it adds functionality.
    @Override
    private void gotHit(int reduction){
        super.gotHit(reduction); // You forgot to call the methods of the superclasses.
        if(new Random().nextDouble() > 0.25){
            simpleShip.gotHit(reduction);
        }
    }

    // This is unnecessary, because it is implicitly done.
    @Override
    public void attack(SpaceShip<?> other){
        super.attack(other);
    }
}

От вас потребуется, если вы учитывая язык программирования, который не вызывает автоматически переопределенный метод без явного обращения к нему.

См. книгу «Банды четырех» «Шаблоны проектирования» для получения дополнительной информации.

0 голосов
/ 26 января 2020

Предполагается, что шаблон декоратора будет подсвечен, чтобы добавить дополнительные функции к кораблям, поскольку базовая функция уже существует на базовом c корабле. Это SimpleShip всегда идет с этими функциями.

Ваше видение шаблона декоратора в основном правильное, но когда вы украшаете корабль, вы должны сохранить основные функции, а также дополнительные. Это означает, что gotHit должен делать то, что SimpleShip делает + дополнительные вещи, которые GuardedShip делает.

Итак, что это значит с точки зрения кода?

Вы должны назвать gotHit() перед тем, как делать дополнительные вещи в украшенных кораблях:

class SneakyShip<T extends Weapon> extends ShipDecorator<T>{
    public SneakyShip(SimpleShip<T> other, T weapon){
        super(other);
    }

    @Override
    private void gotHit(int reduction){
        super.gotHit(reduction); // core behaviour of every ship
        // additional feature of guarded ships
        if(new Random().nextDouble() > 0.25){
            // more damage
        }
    }
}

То, что вы делаете в своем коде, полностью меняет поведение корабля относительно поведения gotHit.

Здесь это некоторые ссылки

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...