Поведение конкретного объекта в предложении If - PullRequest
1 голос
/ 24 января 2012

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

Большая часть кода в методе разрешения применяется ко всем различным типам объектов, которые могут быть поражены, нонекоторые также специфичны для конкретного типа объекта.

Псевдокод выглядит следующим образом:

resolve (Object a) {

if (some test) {
    if (Object a is rect) {
    // do one thing
    } else {
    // do something else thing
} else if (another test) {
    if (Object a is rect) {
    // do one thing
    } else {
    // do something else thing
} else if (third test) {
    if (Object a is rect) {
    // do one thing
    } else {
    // do something else thing
}
}

Однако для новичка это выглядит как суматоха (из-за тестов на тип объекта в каждом предложении if), но я могу 'не совсем понять, как его улучшить?Я мог бы переопределить метод и иметь поведение, основанное на подклассе, который ему передается, но затем я получаю много одинакового кода в обоих методах.

Этот метод проверяет текущее местоположение мяча (верх, низ и т. Д.) И соответствующим образом регулирует скорость мяча.Если объект представляет собой прямоугольник, новая скорость отличается, скажем, от круга.

Может ли кто-нибудь предложить какую-либо помощь?

Ответы [ 2 ]

3 голосов
/ 24 января 2012

Как и предполагалось, шаблон посетителя является хорошей идеей, поскольку он поддерживает модульность кода. Это связано с тем, что код для каждого теста хранится в своем собственном классе и методе, что помогает предотвратить чрезмерную длину и сложность методов.

Теперь это также означает, что вам не нужно проверять, является ли Объект прямоугольником или нет, как это делается с помощью техники, известной как двойная диспетчеризация. При этом GameObject знает, какой это класс класса, и поэтому вызывает соответствующий метод разрешения для посетителя.

Это также помогает в сопровождении, как если бы вам нужно было обращаться с другим подклассом GameObject специально, тогда вы сначала измените интерфейс ResolveVisitor, а затем начнете изменять конкретные реализации посетителей. Если вы случайно забудете об этом, компилятор не позволит вам скомпилировать код и указать на проблему.

Вот подробный пример шаблона посетителя:

void resolve(GameObject obj) {
    if (first test) {
        obj.accept(new FirstTestVisitor());
    } else if (second test) {
        obj.accept(new SecondTestVistor());
    } else {
        obj.accept(new DefaultVisitor());
    }
}

interface GameObject {
    public void accept(ResolveVisitor visitor);
}

interface ResolveVisitor {
    public void resolve(Rectangle rect);
    public void resolve(GameObject obj); // default case
}

class Rectangle implements GameObject {
    public void accept(Visitor visitor) {
        visitor.resolve(this);
        // Rectangle and its subclasses will call resolve(Rectangle)
        // whereas all other GameObjects will call resolve(GameObject)
        // though other GameObjects will need their own accept method
    }
}

class FirstTestVisitor implements ResolveVisitor {
    public void accept(Rectangle rect) {
        // logic for first test and if rect goes here
    }
    public void accept(GameObject obj) {
        // logic for first test and not rect goes here
    }
}
0 голосов
/ 24 января 2012

Вы можете попробовать использовать шаблон посетителя: посетитель

Или вы можете сделать это: resolve(ISomeInterface a) { a.react(ball); } Метод реагирования будет определен в каждом классе иерархии классов.

...