Шаблон дизайна посетителя, Как работать с оператором If-else

Постановка задачи:

Существует три типа машин: Machine1 Machine2 и Machine3. Существует три типа валидаторов: ValidatorX, ValidatorY, ValidatorZ.

Каждый валидатор проверяет каждую машину по-разному.

Напишите классы Java, чтобы проектировать вышеупомянутую проблему.

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

"Validator X валидационная машина Y";

Для этого прежде всего я создал один класс Machine и 3 разных класса Validator.

Machine.java

/**
 * Machine
 * 
 * @author sunny
 *
 */
public class Machine {

    private final String name;

    public Machine(final String name) {
        this.name = name;
    }

    public boolean validate(final Validator validator) {
        return validator.validate(this);
    }

    public String getName() {
        return name;
    }
}

Validator.java

/**
 * This is an abstract class for a Validator
 * 
 * @author sunny
 *
 */
public abstract class Validator {

    private String name;

    public Validator(final String name) {
        this.name = name;
    }

    public boolean validate(final Machine machine) {

        System.out.println("Validator " + getName() + " validating "
                + machine.getName());

        // Here I need to write login corresponding to the machine name
        // I need to write if machine Name is X then do this
        // if machine name is Y then do this.
        // I need to avoid this if else or switch case
        // Is there any other better way to achieve this.

        return true;
    }

    public String getName() {
        return name;
    }
}

ValidatorX.java

/**
 * This is one ValidatorX class that I have created
 * 
 * Similarly I have written ValidatorY and ValidatorZ classes
 * 
 * @author sunny
 *
 */
public class ValidatorX extends Validator {

    public ValidatorX() {
        super("X");
    }

    @Override
    public boolean validate(Machine machine) {
        super.validate(machine);
        return true;
    }
}

TestMain.java

import java.util.ArrayList;
import java.util.List;

/**
 * Test class I have written to test this.
 * 
 * @author sunny
 *
 */
public class TestMain {

    public static void main(String[] args) {

        Validator[] validators = { new ValidatorX(), new ValidatorY(),
                new ValidatorZ() };

        List<Machine> machines = new ArrayList<Machine>();
        machines.add(new Machine("Machine1"));
        machines.add(new Machine("Machine2"));
        machines.add(new Machine("Machine3"));

        for (int i = 0; i < validators.length; i++) {
            for (Machine machine : machines) {
                validators[i].validate(machine);
            }

        }
    }

}

В Validator.java (как вы можете видеть в комментариях) мне нужно написать логин, соответствующий имени машины, мне нужно написать, если имя машины - Machine1, затем сделать это, если имя машины - Machine2, а затем сделать это. Я должен избежать этого, если еще или переключить случай. Есть ли другой лучший способ добиться этого.

2 ответа

Ваше использование шаблона посетителя в порядке, проблема в классе машин.

Из того, что я вижу, класс вашей машины представляет "в зависимости" от имени, другой версии / типа машины. Таким образом, вам нужно if/else, чтобы идентифицировать машину и действовать соответственно.

Ваша проблема может быть решена с помощью абстракции

AbstractMachine - будет классом, представляющим общие функции для каждого типа / категории вашего компьютера>

Таким образом, в нем вы будете иметь по крайней мере следующие функции:

public boolean Validate (...)
public string GetName()
abstract public  void MachineAction(...) = 0;

Поэтому вам придется написать класс Machine1, Machine2, Machine3, и вы будете обязаны "перегрузить" действие MachineAction для каждого дочернего класса.

Функция проверки вашего валидатора будет выглядеть так:

 public boolean validate(final Machine machine) 
 {
    System.out.println("Validator " + getName() + " validating "
            + machine.getName());

    machine.MachineAction(...);    
    return true;
 }

По своей конструкции это лучше, чем использование словаря (карты) функций, и вы всегда будете вызывать правильный.

++ Я бы действительно назвал имя лучше, чем Machine1, Machine2, Machine3 - здесь есть нечто большее, чем разница в "имени"

РЕДАКТИРОВАТЬ::

    MachineA : Child Class (inherits from) Machine

    //Since it inherits from Machine no need to reimplement 
    //Validate/GetName, but we need and it's obligated to 
    //reimplement MachineAction for this subclass.

    override public void MachineAction(...)
    {
       DoThisMachineA();
    }

    private void DoThisMachineA(){...}

в то время как MachineB будет выглядеть так:

    MachineB : Child Class (inherits from) Machine

    //Since it inherits from Machine no need to reimplement 
    //Validate/GetName, but we need and it's obligated to 
    //reimplement MachineAction for this subclass.

    override public void MachineAction(...)
    {
       DoThisMachineB();
    }

    private void DoThisMachineB(){...}

** Обратите внимание, что DoThisMachineB() не существует в классе MachineA и не будет представлен intellisense, и не будет компилироваться вообще, и наоборот.

Тем не менее, в посетителе все, что вам нужно сделать, это вызвать MachineAction(...), чтобы посетитель знал, что это машина, но не тот, какой дочерний тип машины, и какой бы тип машины вы ни использовали, вы будете действовать правильно. MachineAction(..) вызов. Вы можете прочитать об этом, мы называем это полиморфизмом.

Вы можете использовать карту действий.

Map<String, Action> actionMap = new HashMap<>();
actionMap.put("Machine1", new SomeActionOne());
actionMap.put("Machine2", new SomeActionTwo());
actionMap.put("Machine3", new SomeActionThree());


for (int i = 0; i < validators.length; i++) {
   for (Machine machine : machines) {
       validators[i].validate(machine);
       Action action = actionMap.get(machine.getName());
       assert action != null;
       action.doSomething();
   }
}
Другие вопросы по тегам