(二十)Java工具类Diffable、DiffBuilder、Diff比较对象的区别及建造者模式详解

原文链接:https://blog.csdn.net/yaomingyang/article/details/79280209

建造者模式(Builder pattern)使用多个简单的对象一步一步的构建成一个复杂的对象,这种类型的设计模式属于创建型模式,他提供了一种创建对象的最佳方式;
一个Builder类会一步一步的构造最终的对象,该Builder类是独立于其它对象的;
建造者模式主要是解决在软件系统中,有时候面临者一个复杂对象的创建工作,其通常由各个部分的子对象用一定的算法构成,由于需求的变化,这个复杂对象的各个部分经常面临者剧烈的变化,但是将他们组合在一起的算法相对稳定;
  • 1
  • 2
  • 3
  • 4

1.Diffable接口比较两个对象的区别

Diffable类可以比较与其它对象的区别,返回DiffResult对象可以查询不同的列表或者使用 DiffResult.toString()打印区别;
如果d1.equals(d2)或者d1.diff(d2) == ""计算的差异和相等都是一致的,强烈建议实现equals方法来避免差异,如果另外一个实例是null那么d1.diff(null)将会抛出空指针异常;
Diffable是适合单元测试的,可以检索到预期结果和实际结果之间的差异的易读的描述;
  • 1
  • 2
  • 3
  • 4
package org.apache.commons.lang3.builder;

public abstract interface Diffable<T>
{
  public abstract DiffResult diff(T paramT);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

2.Diff类比较对象包装器中对象的字段不同

一个Diff类包含两个Diffable类之间的差异;通常,Diff通过使用Diffable构建DiffResult返回,包含两个对象的差异;
  • 1
  • 2
package org.apache.commons.lang3.builder;

import java.lang.reflect.Type;
import java.util.Map;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.reflect.TypeUtils;
import org.apache.commons.lang3.tuple.Pair;

/**
 * 
 * 差异类
 * @param <T>
 * 
 * @version 1.0
 * @since JDK1.7
 */
public abstract class Diff<T>
  extends Pair<T, T>
{
  private static final long serialVersionUID = 1L;
  private final Type type;
  private final String fieldName;
  /**
   * 给新的字段构建差异化比较器
   * @param fieldName
   */
  protected Diff(String fieldName)
  {
    this.type = ((Type)ObjectUtils.defaultIfNull(TypeUtils.getTypeArguments(getClass(), Diff.class).get(Diff.class.getTypeParameters()[0]), Object.class));


    this.fieldName = fieldName;
  }

/**
 * 
 * 方法描述 获取字段类型
 *
 * @return
 * 
 * @author yaomy
 * @date 2018年2月7日 上午11:43:51
 */
  public final Type getType()
  {
    return this.type;
  }

/**
 * 
 * 方法描述 获取字段名称
 *
 * @return
 * 
 * @author yaomy
 * @date 2018年2月7日 上午11:44:08
 */
  public final String getFieldName()
  {
    return this.fieldName;
  }

/**
 * 返回差异的字符串形式
 */
  public final String toString()
  {
    return String.format("[%s: %s, %s]", new Object[] { this.fieldName, getLeft(), getRight() });
  }

/**
 * 将会抛出UnsupportedOperationException异常
 */
  public final T setValue(T value)
  {
    throw new UnsupportedOperationException("Cannot alter Diff object.");
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79

3.Builder接口被设计为在建造者模式中将类指定为建造者对象

建造器能够创建和配置对象或者结果通常采用多步构建或者是非常复杂的派生;
建造器定义了一个方法,build(),该类必须实现,此方法的结果应该是所有构建操作完成后的最终配置对象和结果;
  • 1
  • 2
  • 3
package common.lang;

import org.apache.commons.lang3.builder.DiffBuilder;
import org.apache.commons.lang3.builder.DiffResult;
import org.apache.commons.lang3.builder.Diffable;
import org.apache.commons.lang3.builder.ToStringStyle;

public class User implements Diffable<User>{

    private int age;
    private String username;

    public User(int age, String username) {
        this.age = age;
        this.username = username;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }


    @Override
    public DiffResult diff(User user) {
        // TODO Auto-generated method stub
        return new DiffBuilder(this, user, ToStringStyle.SHORT_PREFIX_STYLE)
                    .append("age", this.getAge(), user.getAge())
                    .append("username", this.getUsername(), user.getUsername())
                    .build();
    }

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

两个对象作比较如下:

import java.util.Iterator;
import java.util.List;

import org.apache.commons.lang3.builder.Diff;
import org.apache.commons.lang3.builder.DiffResult;

public class StingUtilsTest{

    public static void main(String[] args) {
        User user1 = new User(12, "yao");
        User user2 = new User(123, "yao3");
        DiffResult result = user1.diff(user2);
        System.out.println(result.getNumberOfDiffs());
        List<Diff<?>> list = result.getDiffs();
        for(Iterator<Diff<?>> it=list.iterator();it.hasNext();) {
            Diff<?> diff = it.next();
            System.out.println(diff.getFieldName()+":"+diff.getValue()+"--"+diff.getLeft()+"--"+diff.getRight()+"--"+diff.getKey()+":"+diff.getType());
        }
        System.out.println();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

4.DiffBuilder类协助Diffable.diff方法比较两个对象的差异

DiffBuilder类使用了建造者模式来比较两个对象中参数的差异,具体使用方式如上;


猜你喜欢

转载自blog.csdn.net/jarniyy/article/details/80429467