简体   繁体   English

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

[英]Visitor Design Pattern, How to deal with If-else statement

Problem statement: 问题陈述:

There are three types of Machines, Machine1 Machine2 and Machine3. 机器共有三种类型,即Machine1 Machine2和Machine3。 There are three types of validators, ValidatorX , ValidatorY , ValidatorZ. 验证器有以下三种类型:ValidatorX,ValidatorY和ValidatorZ。

Each Validator validates each machine differently. 每个验证器以不同的方式验证每台计算机。

Write Java classes to design the above problem. 编写Java类来设计上述问题。

The program runs from a main function , which already has the list of validators and machines. 该程序从主要功能运行,该功能已经具有验证器和机器的列表。 Each Validator should print a message during validation 每个验证器应在验证期间打印一条消息

"Validator X validating Machine Y"; “验证者X验证机Y”;

To design this, First of all I have created one Machine class and 3 different Validator classes. 为此,我首先创建了一个Machine类和3个不同的Validator类。

Machine.java 机器.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 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 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);
            }

        }
    }

}

In Validator.java (as you can see in the comments) I need to write login corresponding to the machine name, I need to write if machine Name is Machine1 then do this if machine name is Machine2 then do this. 在Validator.java中(您可以在注释中看到),我需要编写与计算机名称相对应的登录名,如果计算机名称是Machine1,则需要编写登录名,然后如果计算机名称是Machine2,则需要编写登录名。 I need to avoid this if else or switch case. 我需要避免这种情况,否则请切换大小写。 Is there any other better way to achieve this. 还有其他更好的方法来实现这一目标。

You might use an action map. 您可以使用动作图。

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

Your use of the visitor pattern is fine, problem is the Machine Class. 您对访问者模式的使用很好,问题出在机器类上。

From what I see, your machine class represent "depending" on name, different version/type of machine. 据我所知,您的机器类代表“取决于”名称,机器的不同版本/类型。 Therefore you need the if/else to identify the machine and act accordingly. 因此,您需要if / else来识别机器并采取相应的措施。

Your problem coudl be fixe by Abstraction 您的问题可以通过抽象来解决

AbstractMachine - would be the class that represent the shared functions to each of your machine type/categories> AbstractMachine-将是代表每种机器类型/类别的共享功能的类>

So in it you would have at the very least the following functions : 因此,它至少具有以下功能:

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

Therefore you would have to write up the class Machine1, Machine2, Machine3 and you would be obligated to "overload" MachineAction for each child class. 因此,您将不得不编写Machine1,Machine2,Machine3类,并且必须为每个子类“重载” MachineAction。

Your validator's validate function would then look like this : 验证器的validate函数将如下所示:

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

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

By design, it is better than having a Dictionnary(Map) of functions and you are sure to always call the right one. 通过设计,它比具有Dictionnary(Map)函数要好,并且您可以确保始终调用正确的函数。

++ I would really give better name than Machine1, Machine2, Machine3 - there is something bigger than a "name" difference here ++我真的会给比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(){...}

while MachineB would look like this : 而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(){...}

** Note that DoThisMachineB() does not exist in the MachineA class, and would not be presented by the intellisense, and would not compile at all, and vice versa. **请注意,DoThisMachineB()在MachineA类中不存在,并且不会由智能感知提供,也不会编译,反之亦然。

Yet in the visitor, all you would have to do is Call MachineAction(...) has the visitor knows it's a Machine but not which child-type of machine and that what-ever type of machine you are, you will act properly on a MachineAction(..) call. 但是,在访客中,您所要做的就是致电MachineAction(...),让访客知道这是一台机器,但不是哪种子类型的机器以及无论哪种类型的机器,您都可以正常操作MachineAction(..)调用。 You can read on this, we call it polymorphism. 您可以阅读此书,我们称之为多态性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM