首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >测试工具中的设计模式之组合模式

测试工具中的设计模式之组合模式

作者头像
Criss@陈磊
发布2020-11-05 12:34:38
4820
发布2020-11-05 12:34:38
举报
文章被收录于专栏:测试技术圈测试技术圈

在笔者之前一篇介绍策略模式案例II-看DBRider如何导入数据的文章中有提到为了支持某些操作的组合,在这个策略模式中还混合使用了组合模式。 首先还是通过策略模式来看一下类图。

在右下角有一个名为CompsiteOperation的类,从命名上看疑似使用了组合模式。

简单了解一下组合模式Composite Pattern

组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。 这种模式创建了一个包含自己对象组的类。该类提供了修改相同对象组的方式。

说到组合模式,一般都会用树来作为案例,树由树枝和树叶组合而成,而树枝又包含了更小的枝杈或者是树叶。由于这是一个关于结构型的设计模式,是一个比较静态的呈现,会让人感觉有些抽象,以下是笔者从知乎上面一篇文章中抠来的一张图,通过UML序列图的方式来表达组合模式,就更为直观了。

从上图我们可以看出,当客户端Client调用整个树的类CompositeA类的方法doAction()时,由于采用了组合模式,在CompositeA类中存储了以下的节点的组合

  • CompositeB
  • LeafC 因此,CompositeA在执行doAction方法的过程会依次调用它们各自的doAction方法。 类似的,CompositeB中也持有2个节点
  • LeafA
  • LeafB 它们各自的doAction方法会被调用。这样,通过组合模式,只要通过CompositeA,就可以把一连串的doAction动作组合起来供客户端调用。在这个基础上,我们还可以根据业务需要派生出CompositeC等不同的组合。

为什么说CompsiteOperation是采用了组合模式。

首先来看看调用者。前面有提到@DataSet注解有一个strategy属性,指定了若干的数据集插入数据库的策略,这主要是通过SeedStrategy 这个枚举类来实现的。

package com.github.database.rider.core.api.dataset;

/**
 * Created by pestano on 23/07/15.
 */

import org.dbunit.operation.*;

public enum SeedStrategy {
    CLEAN_INSERT(DatabaseOperation.CLEAN_INSERT),
    TRUNCATE_INSERT(new CompositeOperation(DatabaseOperation.TRUNCATE_TABLE, DatabaseOperation.INSERT)),
    INSERT(DatabaseOperation.INSERT),
    REFRESH(DatabaseOperation.REFRESH),
    UPDATE(DatabaseOperation.UPDATE);

    private final DatabaseOperation operation;

    SeedStrategy(DatabaseOperation operation) {
        this.operation = operation;
    }

    public DatabaseOperation getOperation() {
        return operation;
    }
}

这其中有两种策略就属于组合策略,

  • CLEAN_INSERT(DatabaseOperation.CLEAN_INSERT),
  • TRUNCATE_INSERT(new CompositeOperation(DatabaseOperation.TRUNCATE_TABLE, DatabaseOperation.INSERT))

例如CLEAN_INSERT就是先将数据库中目标表清空,然后在执行INSERT操作。

组合类中的自身对象组和遍历方法

作为组合类的标志,CompositeOperation中应该包含了一个容纳DatabaseOperation类及其子类的组合,以及遍历并执行execute方法的execute方法,我们来看一下

package org.dbunit.operation;

import java.sql.SQLException;
import java.util.Arrays;
import org.dbunit.DatabaseUnitException;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.dataset.IDataSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class CompositeOperation extends DatabaseOperation {
    private static final Logger logger = LoggerFactory.getLogger(CompositeOperation.class);
    private final DatabaseOperation[] _actions;

    public CompositeOperation(DatabaseOperation action1, DatabaseOperation action2) {
        this._actions = new DatabaseOperation[]{action1, action2};
    }

    public CompositeOperation(DatabaseOperation[] actions) {
        this._actions = actions;
    }

    public void execute(IDatabaseConnection connection, IDataSet dataSet) throws DatabaseUnitException, SQLException {
        logger.debug("execute(connection={}, , dataSet={}) - start", connection, dataSet);

        for(int i = 0; i < this._actions.length; ++i) {
            DatabaseOperation action = this._actions[i];
            action.execute(connection, dataSet);
        }

    }

//...
}

可以看到,在CompositeOperation类中的确有如下的一个数组 private final DatabaseOperation[] _actions; 以及一个重载的execute方法 public void execute(IDatabaseConnection connection, IDataSet dataSet)

这样,就能将_actions数组中存放的各类型DataBaseOperation按照顺序执行了。

CompositeOperation的UML序列图

参考之前的类图,结合DataBaseRider中的源码,笔者画了下面的一个简化示意图。如前所述,目前有两种策略是使用了组合模式,也就是是CompositeOperation类的两个实例,分别是CLEAN_INSERT和TRUNCATE_INSERT。整个组合的调用过程还是比较清晰的。

如果有看到开源项目中使用的其它设计模式,欢迎留言给笔者提供线索。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-10-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 质问 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简单了解一下组合模式Composite Pattern
  • 为什么说CompsiteOperation是采用了组合模式。
    • 组合类中的自身对象组和遍历方法
      • CompositeOperation的UML序列图
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档