zoukankan      html  css  js  c++  java
  • junit设计模式--组合模式


    • Composite,英语翻译下,复合,组合。
    组合模式有时候又叫做部分-整体模式,它使我们在树形结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元素一样来处理复杂元素,从而使得客户与复杂元素的内部结构解耦。将对象组合成树形结构以表示“部分-整体”的层次结构。Composite模式使得用户对单个对象和组合对象的使用具有一致性。


    • 组合模式(Composite)的组成

    1.Component 抽象构件接口

    为组合的对象声明接口。
    在某些情况下实现从此接口派生出的所有类共有的默认行为。
    定义一个接口可以访问及管理它的多个子部件。


    2.Leaf 叶部件

    在组合中表示叶节点对象,叶节点没有子节点。
    定义组合中接口对象的行为。


    3.Composite 组合类

    定义有子节点(子部件)的部件的行为。
    存储子节点(子部件)。
    在Component接口中实现与子部件相关的操作。


    4.Client 客户端

    通过Component接口控制组合部件的对象。


    OK,现在我们来写一个例子。

    package org.linkinpark.junit.testjunit;
    
    /**
     * @创建作者: LinkinPark
     * @创建时间: 2016年2月4日
     * @功能描述: 抽象构件接口。叶子类和组件类都要实现该接口
     */
    public interface Component
    {
    
    	void doSomething();
    
    }
    


    package org.linkinpark.junit.testjunit;
    
    /**
     * @创建作者: LinkinPark
     * @创建时间: 2016年2月4日
     * @功能描述: 叶子类。注意:叶子类没有子节点
     */
    public class Leaf implements Component
    {
    
    	@Override
    	public void doSomething()
    	{
    		System.out.println("叶子类实现。。。");
    	}
    
    }
    

    package org.linkinpark.junit.testjunit;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @创建作者: LinkinPark
     * @创建时间: 2016年2月4日
     * @功能描述: 组合类。组合类要包含子节点
     */
    public class Composite implements Component
    {
    
    	// List的类型是接口类型Component,这样就既可以放Leaf,又可以放Composite
    	private List<Component> list = new ArrayList<>();
    
    	public void add(Component component)
    	{
    		list.add(component);
    	}
    
    	public void remove(Component component)
    	{
    		list.remove(component);
    	}
    
    	public List<Component> getList()
    	{
    		return list;
    	}
    
    	@Override
    	public void doSomething()
    	{
    		// 组合模式精髓。
    		for (Component component : list)
    		{
    			// 如果是叶子,直接执行。如果是复合的,则继续遍历其中包含的list。
    			component.doSomething();
    		}
    	}
    
    }
    


    package org.linkinpark.junit.testjunit;
    
    import org.junit.Test;
    
    public class CompositeTest
    {
    
    	@Test
    	public void testDoSomething()
    	{
    		Leaf leaf1 = new Leaf();
    		Leaf leaf2 = new Leaf();
    		Composite composite = new Composite();
    		composite.add(leaf1);
    		composite.add(leaf2);
    		
    		Leaf leaf3 = new Leaf();
    		Leaf leaf4 = new Leaf();
    		Composite composite1 = new Composite();
    		// 组合模式来了,下面让组合类中添加2个子节点和一个组合类节点
    		composite1.add(leaf3);
    		composite1.add(leaf4);
    		composite1.add(composite);
    		
    		composite1.doSomething();
    	}
    
    }
    


    上面的代码写了一个叶子类,一个组合类,一个子类和组合类面向的接口,还有一个测试了,在测试类中我们往组合类中添加了2个叶子类,添加了一个包含2个叶子类的组合类,然后我们调用doSomething()方法来看下输出:

    叶子类实现。。。
    叶子类实现。。。
    叶子类实现。。。
    叶子类实现。。。


    在JUnit中的应用

      JUnit中的测试套件Suite是一个复杂元素,但是对于用户来说,TestCase和TestSuite在使用时无需进行区分,这就是应用了组合模式。OK,现在来看看junit源码中组合模式的使用:

    Test:抽象构建接口:

    package org.linkinpark.commons.framework;
    
    /**
     * @创建作者: LinkinPark
     * @创建时间: 2016年1月21日
     * @功能描述: 测试接口,所有的测试类都要实现这个接口
     */
    public interface Test
    {
    	/**
    	 * @创建时间: 2016年1月21日
    	 * @相关参数: @return
    	 * @功能描述: 测试用例执行的数量
    	 */
    	public abstract int countTestCases();
    
    	/**
    	 * @创建时间: 2016年1月21日
    	 * @相关参数: @param result
    	 * @功能描述: 开始执行一个测试用例然后+收集测试结果
    	 */
    	public abstract void run(TestResult result);
    }

    TestCase:叶子类

    public abstract class TestCase extends Assert implements Test
    {
        public int countTestCases()
        {
            return 1;
        }
    
        public void run(TestResult result)
        {
            result.run(this);
        }
    
    }

    TestSuite:组合类

    public class TestSuite implements Test
    {
        private String fName; // 测试类的类名,注意,TestCase中的fName是方法名。
        private Vector<Test> fTests = new Vector<Test>(10); // 用来装用例的,可以的是TestCase,也可以是TestSuite
    
        /**
         * @创建时间: 2016年1月22日
         * @相关参数: @param test
         * @功能描述: 添加一个测试
         */
        public TestSuite addTest(Test test)
        {
            fTests.add(test);
            return this;
        }
        
        /**
         * @创建时间: 2016年1月22日
         * @相关参数: @param testClass
         * @功能描述: 直接添加测试类到suite中
         */
        public TestSuite addTestSuite(Class<? extends TestCase> testClass)
        {
            addTest(new TestSuite(testClass));
            return this;
        }
    
        public Enumeration<Test> tests()
        {
            return fTests.elements();
        }
    
        /**
         * 统计测试用例的个数
         */
        public int countTestCases()
        {
            int count = 0;
            for (Test each : fTests)
            {
                count += each.countTestCases();
            }
            return count;
        }
    
        /**
         * 运行测试
         */
        public void run(TestResult result)
        {
            for (Test each : fTests)
            {
                if (result.shouldStop())
                {
                    break;
                }
                runTest(each, result);
            }
        }
    
        public void runTest(Test test, TestResult result)
        {
            test.run(result);
        }
    }
    
        



    OK,代码不多,但是利用了compiste模式。在TestSuite中,可以通过addTest()方法向TestSuite加入测试用例,也可以通过addTestSuite()方法向TestSuite加入用例集合。运行测试是通过run()方法,如果该实例是TestCase,那么执行真正的测试,如果该实例是TestSuite,那么就会通过TestSuite维护的fTests来访问每一个TestCase测试用例,然后才开始执行测试。因为这里的TestSuite也实现了Test组合类接口,所以我们可以往TestSuite中添加TestCase,也可以往TestSuite中添加TestSuite。注意:如果往TestSuite中添加的也是TestSuite,执行的时候会进行一次或多次递归。


  • 相关阅读:
    PAT甲题题解-1030. Travel Plan (30)-最短路+输出路径
    PAT甲题题解-1029. Median (25)-求两序列的中位数,题目更新了之后不水了
    PAT甲题题解-1028. List Sorting (25)-水排序
    BZOJ 1492 货币兑换Cash
    Codeforces 276D Little Girl and Maximum XOR
    Codeforces 526E Transmitting Levels
    Codeforces 335B Palindrome
    BZOJ 2527 Meteors
    Codeforces 449D Jzzhu and Numbers
    FJ省队集训DAY4 T3
  • 原文地址:https://www.cnblogs.com/LinkinPark/p/5232881.html
Copyright © 2011-2022 走看看