lundi 25 mai 2020

How to clone a parameterized prototype?

I want to clone a prototype but with some changes. I want to pass the arguments that need to change. I have several candidate solutions but I'm not sure what is the best way. It may be none of them.

Here I have 3 classes, Prototype1, Prototype2 and Prototype3. Each one of them uses a different way of cloning. The class PrototypeBase is just for defining the common behavior among the three classes.

Each class is cloned in the main function.

public class Main {

    public static void main(String[] args) {

        var prototype1 = new Prototype1("a", "b", "c");
        var prototype1Clone = prototype1.clone(null, "bbb", null);

        var prototype2 = new Prototype2("a", "b", "c");
        var prototype2Clone = prototype2.clone();
        prototype2Clone.setB("bbb");

        var prototype3 = new Prototype3("a", "b", "c");
        var prototype3Clone = new Prototype3(null, "bbb", null);
        prototype3Clone.clone(prototype3);
    }
}

class PrototypeBase
{
    protected String a, b, c;

    public void setA(String a) {
        this.a = a;
    }

    public void setB(String b) {
        this.b = b;
    }

    public void setC(String c) {
        this.c = c;
    }

    @Override
    public String toString() {
        return "Prototype{" +
                "a='" + a + '\'' +
                ", b='" + b + '\'' +
                ", c='" + c + '\'' +
                '}';
    }
}

class Prototype1 extends PrototypeBase
{

    public Prototype1(String a, String b, String c) {
        this.a = a;
        this.b = b;
        this.c = c;
    }

    // Won't have a uniform interface across all prototypes
    // since each prototype may have a different number of fields.
    public Prototype1 clone(String a, String b, String c)
    {
        if (a == null)
            a = this.a;

        if (b == null)
            b = this.b;

        if (c == null)
            c = this.c;

        return new Prototype1(a, b, c);
    }
}

class Prototype2 extends PrototypeBase
{
    public Prototype2(String a, String b, String c) {
        this.a = a;
        this.b = b;
        this.c = c;
    }

    // a, b or c may be expensive to copy. It would
    // be better if we can pass the parameters directly
    // without copying all members first.
    public Prototype2 clone()
    {
        return new Prototype2(a, b, c);
    }
}

class Prototype3 extends PrototypeBase
{
    public Prototype3() {}

    public Prototype3(String a, String b, String c) {
        this.a = a;
        this.b = b;
        this.c = c;
    }

    // Not so intuitive. Usually, people just
    // ask for a clone and get the result back.
    public void clone(Prototype3 prototype)
    {
        if (this.a == null)
            this.a = prototype.a;

        if (this.b == null)
            this.b = prototype.b;

        if (this.c == null)
            this.c = prototype.c;
    }
}

Each one has its drawbacks. What is the best way to clone a prototype when wanting some fields to have a different value?

Aucun commentaire:

Enregistrer un commentaire