2

Я искал об этом подэлементе arround здесь, в Stack Overflow. Я нашел следующее решение:Избегайте использования InstanceOf с шаблоном посетителя - Java

Explanation of Visitor Pattern

Теперь мое дело всего напоминает этому. Мне нужно, однако, избегать использования «instanceOf».

У меня есть игра, которая имеет башни, названные MonkeyTower, CannonTower, OctoTower ... и некоторые другие классы используют instanceOf для сравнения.

Вот пример класса, который использует instanceOf:

BloonsTower.java

public void mousePressed(Point p) { 
     Tower t = null; 
     selectedTower = towerInfo[ insertTowerIdx ].getTower(); 

     if(selectedTower instanceof MonkeyTower) 
      t = tCreator.createMonkey(); 
     else if(selectedTower instanceof OctoTower) 
      t = tCreator.createOctogonal(); 
     else if(selectedTower instanceof CannonTower) 
      t = tCreator.createCannon(); 
     else if(selectedTower instanceof MortarTower) 
      t = tCreator.createMortar(); 
     setMoney(money - towerInfo[ insertTowerIdx ].getPrice()); 
     t.setPosition(p); 
     world.addTower(t); 
     currentState = new SelectTowerState(); 
    } 

ManipulatorCreator.java

if(t instanceof MonkeyTower) 
     return null; 
    else if(t instanceof OctoTower) 
     return new OctoManipulator(t); 
    else if(t instanceof CannonTower) 
     return null; 
    else if(t instanceof MortarTower) 
     return new MortarManipulator((MortarTower)t); 
    return man; 

И GameWriter:

public void saveFile(File file, int round, int money, int lives, World m) throws IOException { 
    PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(file))); 

    out.println(round); 
    out.println(money); 
    out.println(lives); 
    Tower []torres = m.getTowers(); 
    out.println(torres.length); // escrever o nº de torres 
    for(Tower t : torres){ 
     Point p = t.getComponent().getPosicao(); 
     // escrever a posição e o tipo de torre 
     out.print(p.x+"\t" + p.y+"\t"); 
     if(t instanceof MonkeyTower) 
      out.println("macaco"); 
     else if(t instanceof OctoTower) 
      out.println("octo"); 
     else if(t instanceof CannonTower) 
      out.println("canhao"); 
     else if(t instanceof MortarTower) 
      out.println("morteiro"); 
    } 

    out.close(); 
} 

Что я создал класс для посетителей, которая посещает каждую башню:

public class TowerVisitor implements Visitor{ 

    public void visit(MonkeyTower monkey) { 
     // TODO Auto-generated method stub 
    } 

    public void visit(CannonTower cannon) { 
     // TODO Auto-generated method stub 
    } 

    public void visit(MortarTower mortar) { 
     // TODO Auto-generated method stub 
    } 

    public void visit(OctoTower octo) { 
     // TODO Auto-generated method stub 
    } 
} 

И в каждой башне я создал есть метод accept, который возвращает себе

Теперь я застрял в что положить внутри метода visit и как использовать шаблон для переключения всех instanceOf.

Спасибо.

+3

Я не понимаю, почему вам нужен шаблон посетителя. Почему бы не создать абстрактные методы: 'Tower.createTower()', 'Tower.createManipulator() 'и т. д.? – shmosel

+0

Вам нужен шаблон FactoryMethod, а не посетитель. –

+0

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

ответ

0

Вы должны использовать FactoryMethod или AbstractFactory шаблон (если вы хотите создать ManipulatorDactory independentemt of Tower) вместо Visitor.

Посмотрите на это Factory Method и Abstract Facotry для получения более подробной информации.

Некоторые примеры кода:

public class FactoryMethodDemo{ 

    public FactoryMethodDemo(){ 

    } 
    public Tower getTower(String type){ 
     if (type.equalsIgnoreCase("monkey")){ 
      return new MonkeyTower(); 
     }else if (type.equalsIgnoreCase("octo")){ 
      return new OctoTower(); 
     }else if (type.equalsIgnoreCase("canon")){ 
      return new CannonTower(); 
     }else if (type.equalsIgnoreCase("mortal")){ 
      return new MortarTower(); 
     } 
     return null; 
    } 
    public static void main(String args[]){ 
     FactoryMethodDemo factory = new FactoryMethodDemo(); 
     Tower tower = factory.getTower(args[0]); 
     System.out.println("Tower:"+tower); 
    } 
} 
abstract class Tower{ 
    Manipulator manipulator = null; 
    public Tower(){ 

    } 
    public String toString(){ 
     return this.getClass().getSimpleName()+":manipulator:"+manipulator; 
    } 
    public Manipulator getManipulator(){ 
     return manipulator; 
    } 
} 
class MonkeyTower extends Tower{ 
    public MonkeyTower(){ 

    } 
} 
class OctoTower extends Tower{ 
    public OctoTower(){ 
     manipulator = new OctoManipulator(); 
    } 

} 
class CannonTower extends Tower{ 
    public CannonTower(){ 

    } 
} 
class MortarTower extends Tower{ 
    public MortarTower(){ 
     manipulator = new MortarManipulator(); 
    } 

} 
class Manipulator{ 

} 
class OctoManipulator extends Manipulator{ 

} 
class MortarManipulator extends Manipulator{ 

} 

выход:

D:\Study\Java>java FactoryMethodDemo monkey 
Tower:MonkeyTower:manipulator:null 

D:\Study\Java>java FactoryMethodDemo mortal 
Tower:MortarTower:manipulator:[email protected] 

D:\Study\Java>java FactoryMethodDemo octo 
Tower:OctoTower:manipulator:[email protected] 

D:\Study\Java>java FactoryMethodDemo canon 
Tower:CannonTower:manipulator:null 

Похожие SE вопросы:

Factory Pattern. When to use factory methods?

What is the basic difference between the Factory and Abstract Factory Patterns?

+0

абстрактный завод не должен использоваться, когда мы хотим создать разные типы famillies? мы работаем только с башней типа ->. в этом случае нам нужно вернуть новые объекты башен, не так ли? но не во всех случаях. я думал о продолжении работы с посетителем, но для случаев, которые должны возвращать новый объект, реализовать прототип – user1987003

+0

В моем ответе реализован только шаблон FactoryMethod. Бетонная башня возвращает правильный объект манипулятора. Я обработал условия, о которых вы указали. –

2

Вы должны использовать шаблоны ядра Object Oriented Programming, а именно наследование, а не шаблон посетителя. У вас есть несколько различных типов башен и подобные действия (создавать, манипулировать, toString и т. Д.), Которые должны быть реализованы по-разному для каждого типа башни. Классический пример наследования.

public abstract class Tower { 
    public abstract Tower create(); 
    public abstract Manipulator manipulate(); 
} 

--- 

public class MortarTower extends Tower { 
    @Override 
    public MortarTower create() { 
    return new MortarTower(); 
    } 

    @Override 
    public MortarManipulator manipulate() { 
    return new MortarManipulator(this); 
    } 

    @Override 
    public String toString() { 
    return "morteiro"; 
    } 
} 

--- 

public void mousePressed(Point p) { 
    selectedTower = towerInfo[insertTowerIdx].getTower(); 
    setMoney(money - towerInfo[insertTowerIdx].getPrice()); 
    Tower t = selectedTower.create(); 
    t.setPosition(p); 
    world.addTower(t); 
    currentState = new SelectTowerState(); 
} 

И так далее.

+0

Обратите внимание, что шаблон посетителя _is_ ООП. – jaco0646

+0

Конечно, вы правы. Надеюсь, вы знаете, что я имею в виду. Можете ли вы предложить лучший способ его формулировки? «Основной ООП»? «Основной ООП»? – dimo414

+0

Если бы было намерение следить за комментарием @ ravindra и реализовывать шаблон [Factory Method pattern] (https://sourcemaking.com/design_patterns/factory_method), то я бы назвал его «:« Вы должны использовать шаблон Factory Method, а не посетитель pattern._ " – jaco0646

 Смежные вопросы

  • Нет связанных вопросов^_^