访问者设计模式,如何处理If-else语句

时间:2014-07-12 07:51:15

标签: java design-patterns visitor-pattern

问题陈述:

有三种类型的机器,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则执行此操作然后执行此操作。 如果是else或switch case,我需要避免这种情况。还有其他更好的方法来实现这一目标。

2 个答案:

答案 0 :(得分:0)

您可以使用动作地图。

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();
   }
}

答案 1 :(得分:0)

您使用访客模式很好,问题是机器类。

从我看到的,您的机器类代表“依赖”名称,不同版本/类型的机器。因此,您需要if / else来识别机器并采取相应的行动。

你的问题可以通过抽象解决

AbstractMachine - 将代表每个机器类型/类别的共享函数的类&gt;

所以在其中你至少会有以下功能:

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更好的名字 - 这里有一个比“名字”更大的东西

EDIT ::

    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呈现,也根本不会编译,反之亦然。

然而在访问者中,你所要做的就是Call MachineAction(...)让访问者知道它是一台机器而不是哪种儿童机器和你曾经使用过什么类型的机器,你会在MachineAction(..)调用上正常运行。你可以读到这个,我们称之为多态。