责任链模式

时间:2012-11-03 10:18:09

标签: java unit-testing design-patterns chain-of-responsibility

我正在尝试实现责任链模式,但似乎我遗漏了一些东西,因为在具体的类中,setnexthandler没有设置下一个但总是相同的。我想我的错误是在else statems next.setNextHandler(next)中的processMalfunction()方法的具体类中;我认为它应该是next.setNextHandler(Severity.Medium)的第一个。所以这是代码,如果你可以看看。这是代码。

public interface MalfunctionHandler 
{
    public void processMalfunction(Malfunction malfunciton);
    public void setNextHandler(MalfunctionHandler handler);
}

public enum Severity 
{
    TRIVIAL, LOW, MEDIUM, HIGH
}

public class Malfunction
{
    /**
     * severity is a type of Severity 
     */
    Severity severity;

    /**
     * @param description describes the severity of the problem
     */
    String description;

    Malfunction(Severity severity, String description)
    {
        if(description == null)
        {
            description = "No description available. Probably serious.";
        }

        if(description.isEmpty())
        {
            description = "No description available. Probably serious.";
        }

        this.severity = severity;
        this.description = description;
    }

    public Severity getSeverity() 
    {
        return severity;
    }

    public String getDescription()
    {
        return description;
    }

    public void setSeverity(Severity severity)
    {
        this.severity = severity;
    }

    public void setDescription(String description)
    {
        this.description = description;
    }
}

public class SpaceMonkey implements MalfunctionHandler 
{

    Severity severity;
    MalfunctionHandler next;
    File read = new File("expected-bronze.txt");
    File f = new File("log-bronze.txt");

    SpaceMonkey(Severity severity)
    {
        this.severity = severity;
        System.out.println(FileUtility.readFile(read));
    }

    @Override
    public void processMalfunction(Malfunction malfunction)
    {
        if (malfunction.getSeverity() == Severity.LOW)
        {
           final String[] splits = FileUtility.readFile(read).split("problem.");
            for (String asset : splits)
            {
                if (asset.contains("Space monkey"))
                {
                     FileUtility.writeFile(f, asset + "problem."); 
                     System.out.println(asset + "problem.");
                }
            }
        }
        else
        {
            next.setNextHandler(next);
        }
    }

    @Override
    public void setNextHandler(MalfunctionHandler next)
    {
        this.next = next;
    }
}

public class ServiceRobot implements MalfunctionHandler
{

    Severity severity;
    MalfunctionHandler next;
     File read = new File("expected-bronze.txt");
      File f = new File("log-bronze.txt");

    ServiceRobot(Severity severity)
    {
        this.severity = severity;
    }


    @Override
    public void processMalfunction(Malfunction malfuntion) 
    {


        if (this.severity == severity)
        {
            String[] splits = FileUtility.readFile(read).split("problem.");
         for(String asset : splits)
        {
            if(asset.contains("Service robot"))
            {                  
                 FileUtility.writeFile(f, asset + "problem."); 
                 System.out.println(asset + "problem.");

            }
        }
        }
        else
        {
            next.setNextHandler(next);
        }
    }

    @Override
    public void setNextHandler(MalfunctionHandler next)
    {
        this.next = next;
    }

}

public class Engineer implements MalfunctionHandler
{

    Severity severity;
    MalfunctionHandler next;
    File read = new File("expected-bronze.txt");

    Engineer(Severity severity)
    {
        this.severity = severity;
    }


    @Override
    public void processMalfunction(Malfunction malfuntion)
    {
        File f = new File("log-bronze.txt");

        if (this.severity == severity)
        {
            String[] splits = FileUtility.readFile(read).split("problem.");
         for(String asset : splits)
        {
            if(asset.contains("Engineer"))
            {
                 FileUtility.writeFile(f, asset + "problem."); 
                 System.out.println(asset + "problem.");

            }
        }
        }
        else
        {
            next.setNextHandler(next);
        }
    }

    @Override
    public void setNextHandler(MalfunctionHandler next)
    {
        this.next = next;
    }

}

public class Captain implements MalfunctionHandler
{
    Severity severity;
    MalfunctionHandler next;
    File read = new File("expected-bronze.txt");

    Captain(Severity severity)
    {
        this.severity = severity;
    }
    @Override
    public void processMalfunction(Malfunction malfuntion)
    {
        File f = new File("log-bronze.txt");

        if (this.severity == severity)
        {
            String[] splits = FileUtility.readFile(read).split("problem.");
         for(String asset : splits)
        {
            if(asset.contains("Captain"))
            {
                 FileUtility.writeFile(f, asset + "problem."); 
                 System.out.println(asset + "problem.");

            }
        }
        }
        else
        {
            next.setNextHandler(next);
        }
    }

    @Override
    public void setNextHandler(MalfunctionHandler next)
    {
        this.next = next;
    }

}

public class FileUtility 
{

    /** This method appends a single string to a text file.
     * 
     * @param f The file to write to
     * @param entry The string to append
     */
    public static void writeFile(File f, String entry) 
    {
        try 
        {
            final BufferedWriter out = new BufferedWriter(new FileWriter(f, true));
            out.write(entry);
            out.close();
        } catch (IOException e) 
        {
            System.err.println("Problem writing to the file");
        }
    }

    /** This method resets the named text file.
     * 
     * @param f The file to reset
     */
    public static void resetFile(File f) {
        try {
            final BufferedWriter out = new BufferedWriter(new FileWriter(f, false));
            out.write("");
            out.close();
        } catch (IOException e) {
            System.err.println("Problem reset the file");
        }
    }

    /** This method reads the contents of a text file.
     * 
     * @param f The file to read from
     * @return the contents of the text file as a single string
     */
    public static String readFile(File f) {
        final StringBuilder sb = new StringBuilder();
        try {
            final Scanner scanner = new Scanner(f);
            while (scanner.hasNextLine()) {
                sb.append(scanner.nextLine());
            }
            scanner.close();
        } catch (FileNotFoundException e) {
            System.err.println("Problem reading from file");
        }
        return sb.toString();
    }
}


public class MalfunctionHandlerTest {

    /**
     * No-args constructor.
     */
    public MalfunctionHandlerTest() {
    }

    /**
     * Test of processMalfunction method.
     */
    @Test
    public void testProcessMalfunction() {

        // Instanciate malfunction handlers
        final SpaceMonkey sm = new SpaceMonkey(Severity.TRIVIAL);
        final ServiceRobot sr = new ServiceRobot(Severity.LOW);
        final Engineer e = new Engineer(Severity.MEDIUM);
        final Captain c = new Captain(Severity.HIGH);

        // Construct chain of responsbility
        sm.setNextHandler(sr); 
        sr.setNextHandler(e);
        e.setNextHandler(c);

        // Create malfunctions
        final Malfunction m1 = new Malfunction(Severity.HIGH, "Life support error. Oxygen "
                 + "Recycling unit damaged, running at half efficiency");      
        final Malfunction m2  = new Malfunction(Severity.LOW, "Communications error. Cannot "
                + "find Jazz FM");
        final Malfunction m3 = new Malfunction(Severity.MEDIUM, "Power supply error. Solar Panel "
                + "2 damaged, running at 31.3333% efficiency");
        final Malfunction m4 = new Malfunction(Severity.MEDIUM, "Thermal regulation error. Sensor "
                + "damaged, manual temperature regulation needed");
        final Malfunction m5 = new Malfunction(Severity.TRIVIAL, "Trash can full on C-Desk.");
        final Malfunction m6 = new Malfunction(Severity.LOW, "Shower plug hole full of monkey hair");
        final Malfunction m7 = new Malfunction(Severity.HIGH, "Proximity alert. Collision imminent");

        // Clean log file
        FileUtility.resetFile(new File("log-bronze.txt"));

        // Process malfunctions
        sm.processMalfunction(m1);
        sm.processMalfunction(m2);
        sm.processMalfunction(m3);
        sm.processMalfunction(m4);
        sm.processMalfunction(m5);
        sm.processMalfunction(m6);
        sm.processMalfunction(m7);

        // Check log file
        final String actualOutput = FileUtility.readFile(new File("log-bronze.txt"));
        final String expectedOutput = FileUtility.readFile(new File("expected-bronze.txt"));
        assertEquals(actualOutput, expectedOutput);
    }
}

1 个答案:

答案 0 :(得分:5)

我在这里看不到任何链设置。模式的原则是让链的每个链接都起作用,然后以某种方式调用下一个链接。

因此,方法应如下所示:

public void processMalfunction(Malfunction malfunction) {
    doSomething();
    this.next.processMalfunction(malfunction);
}

当然,应该使用类似

之类的东西设置链
Link1 start = new Link1();
Link2 link2 = new Link2();
start.setNextHandler(link2);
Link3 link3 = new Link3();
link2.setNextHandler(link3);
...

您当前的代码包括在某些条件为真时执行某些操作,否则将下一个处理程序的下一个处理程序分配给自身:

next.setNextHandler(next);