创建一个通用函数来复制不同的对象

Noo*_*tor 3 java copy object java-8

所以我有,我需要一个用例复制一个objectclassES(类可以根据在工厂输入类型而变化.

这是我想要做的样本

public interface DataUtil {

    // the main wrapper 
    static Object copyObject(Object payload){
        if(payload instanceof Human))
            return copyEntry((Human) payload);
        if(payload instanceof Car))
            return copyEntry((Car) payload);
        if(payload instanceof Planet))
            return copyEntry((Planet) payload);        
        return payload;
    }

    static Human copyEntry(Human human) {
        return Human.builder()
                .name(human.getName())
                .age(human.getAge())
                .build();
    }

    static Car copyEntry(Car car) {
        return Car.builder()
                .model(car.getModel())
                .brand(car.getBrand())
                .build();
    }

    static Planet copyEntry(Planet planet) {
        // return builder like previous
    }
}
Run Code Online (Sandbox Code Playgroud)

如果你看一下copyObject函数,它会按预期完成工作,但是他的问题是返回类型.目前,为了使自己兼容,它返回一个,Object但我宁愿返回它特定的类对象(例如Human或说Car)

有没有办法通过Generics(使用<T>)完成这项工作?或者这首先是一个糟糕的做法?

dav*_*xxx 6

有没有办法通过Generics(使用)完成这项工作?或者这首先是一个糟糕的做法?

这是一个糟糕的方法,因为您收到参数a Object.
你不能从中推断具体类型:而instanceof你使用的是.这不是一个好方法.
这里有两个想法(足够相关)

1)介绍可复制的界面

您可以引入一个接口,您要复制的对象的类实现:

public interface Copyable<T> {
    T copy(T t);
}
Run Code Online (Sandbox Code Playgroud)

可以实施,如:

public class Human implements Copyable<Human> {

   @Override
   public Human copy(Human t) {
       return    Human.builder()
                     .name(human.getName())
                     .age(human.getAge())
                     .build();
   }

}
Run Code Online (Sandbox Code Playgroud)

所以一般的copy()方法可能如下所示:

// the main wrapper
static <T extends Copyable<T>> T copyObject(T payload) {
    return payload.copy(payload);
}
Run Code Online (Sandbox Code Playgroud)

你可以用这种方式使用它:

Human human = new Human();
// set some fields  ...
Human copiedHuman = copyObject(human); // compile
Car copiedCar = copyObject(human); // doesn't compile
Run Code Online (Sandbox Code Playgroud)

2)使用访客模式

作为替代方案,它也是访问者模式的一个好例子:您希望根据参数的具体类型应用处理.
它允许将复制操作组合在一起,就像在实际代码中一样.

一般copyObject()方法可以依赖于CopyVisitor根据参数的具体类型进行复制:

@SuppressWarnings("unchecked")
static <T extends Visited> T copyObject(T payload) {
    CopyVisitor visitor = new CopyVisitor();
    payload.accept(visitor);
    return (T) visitor.getCopy();
}
Run Code Online (Sandbox Code Playgroud)

在哪里CopyVisitor实现经典Visitor界面:

public interface Visitor {  
    void visitHuman(Human human);
    void visitCar(Car car);
    void visitPlanet(Planet planet);
}
Run Code Online (Sandbox Code Playgroud)

通过这种方式 :

public class CopyVisitor implements Visitor {

    private Visited copy;

    @Override
    public void visitHuman(Human human) {
        copy = Human.builder()
                    .name(human.getName())
                    .age(human.getAge())
                    .build();

    }

    @Override
    public void visitCar(Car car) {
        copy = Car.builder()
                  .model(car.getModel())
                  .brand(car.getBrand())
                  .build();
    }

    @Override
    public void visitPlanet(Planet planet) {
        //...
    }

    public Visited getCopy() {
        return copy;
    }

}
Run Code Online (Sandbox Code Playgroud)

被访问的类(Car,Human,Plan)将实现一个特定的接口来"接受"访问者:

public interface Visited {
    void accept(Visitor visitor);
}
Run Code Online (Sandbox Code Playgroud)

如 :

public class Human implements Visited {

    @Override
    public void accept(Visitor visitor) {
        visitor.visitHuman(this);
    }

}
Run Code Online (Sandbox Code Playgroud)

所以你可以用copy()这种方式使用这个方法:

Human human = new Human();
// set some fields  ...
Human copiedHuman = copyObject(human); // compile
Car copiedCar = copyObject(human); // doesn't compile
Run Code Online (Sandbox Code Playgroud)