Are all of these method signatures valid for simple factory pattern?

心已入冬 提交于 2019-12-11 04:26:59

问题


I am learnig the simple factory pattern, and I would like to know if all the methods in my factory are valid for such a pattern:

public class Bmw implements Car {
private String color;
private boolean hasXDrive;

public Bmw() {
}

public Bmw(String color) {
    this.color = color;
}

public Bmw(String color, boolean hasXDrive) {
    this.color = color;
    this.hasXDrive = hasXDrive;
}

public String getColor() {
    return color;
}

public void setColor(String color) {
    this.color = color;
}

public boolean isHasXDrive() {
    return hasXDrive;
}

public void setHasXDrive(boolean hasXDrive) {
    this.hasXDrive = hasXDrive;
}
}


public class Audi implements Car {
private String color;
private int turnAssistLevel;

public Audi() {
}

public Audi(String color) {
    this.color = color;
}

public Audi(String color, int turnAssistLevel) {
    this.color = color;
    this.turnAssistLevel = turnAssistLevel;
}

public String getColor() {
    return color;
}

public void setColor(String color) {
    this.color = color;
}

public int getTurnAssistLevel() {
    return turnAssistLevel;
}

public void setTurnAssistLevel(int turnAssistLevel) {
    this.turnAssistLevel = turnAssistLevel;
}
}


public class SimpleCarFactory {

// 1. make empty cars
public Car makeCar(CarType carType) {
    switch (carType) {
        case AUDI:
            return new Audi();
        case BMW:
            return new Bmw();
        default:
            throw new RuntimeException("No such car type!");
    }
}

// 2. make cars with colors
public Car makeCarWithColor(CarType carType, String color) {
    switch (carType) {
        case AUDI:
            return new Audi(color);
        case BMW:
            return new Bmw(color);
        default:
            throw new RuntimeException("No such car type!");
    }
}

// 3. BMW has an option that differentiate it from any other car. We cannot use a general car factory anymore
public Car makeBmw(String color, boolean hasXDrive) {
    return new Bmw(color, hasXDrive);
}

// 4. Audi has a turnAssistLevel option
public Car makeAudi(String color, int turnAssistLevel) {
    return new Audi(color, turnAssistLevel);
}

// 5. The same as #1, only it is static now make empty cars
public static Car staticMakeCar(CarType carType) {
    switch (carType) {
        case AUDI:
            return new Audi();
        case BMW:
            return new Bmw();
        default:
            throw new RuntimeException("No such car type!");
    }
}
}

I've added in code comments the variants of the methods. I'm asking these question because normally, you create a subclass based on some discriminator (CarType). But you can also have constructor parameters.

Also, I'm not sure what to do when your related objects have different constructors.

Please tell me which of the methods from SimpleCarFactory are qualified to follow the simple factory pattern?

Kind regards,


回答1:


It all depends on what is your factory is going to be used for.

1) If you are going to pass this factory to some generic instantiator then your factory must implement some interface common to all factories used by that instantiator. This interface is likely to have single method with generic options:

public interface CarFactory {
    Car makeCar(CarOptions options);
}

2) If you are going to invoke your factory "manually" from different parts of your code, then I would say your approach is right. makeAudi("red", true) looks much more readable than makeCar(new CarOptions(CarType.AUDI, "red", ...)).




回答2:


I'd create an CarOptions object and use that rather than having so many different methods.

public class CarOptions {
    private String color;
    private CarType carType;

    public String getColor() {
        return this.color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public CarType getCarType() {
        return this.carType;
    }

    public void setCarType(CarType carType) {
        this.carType = carType;
    }
}

And then a simple makeCar method which takes the CarOptions object.

public Car makeCar(CarOptions options) {
    switch (options.getCarType()) {
        case AUDI:
            return new Audi(options.getColor());
        case BMW:
            return new Bmw(options.getColor());
        default:
            throw new RuntimeException("No such car type!");
    }
}

The advantage of this is you can then create a BMWCarOptions class:

public class BMWCarOptions extends CarOptions {
    private boolean hasXDrive;

    public boolean getHasXDrive() {
        return this.hasXDrive;
    }

    public void setHasXDrive(boolean hasXDrive) {
        this.hasXDrive = hasXDrive;
    }
}

You can then still pass this into the makeCar method.




回答3:


"Are they valid" yes.

"Are they optimal" no.

You aren't overloading the methods, and I think that would help solve your problem.

 public Car makeCar(CarType carType)
                throws NoCarExistsException 
 public Car makeCar(CarType carType, Color color)
                throws NoCarExistsException 
 public Car makeCar(CarType carType, Color color, Options options) 
                throws NoCarExistsException 
 // where Options is a container class with hashmap 
 // (or one of many other valid impl. possibilities)  with all the options. 

And just have all the logic of "does this combo of options exist" be in the factory logic.

Also could have 'Color' be an 'Option' too.


Note: The benefit of this is that the Factory's user can just make a list of options they want and either gets the car or an exception. Much simpler to use, but means the logic has to exist in the Factory (where I'd argue it should be) instead of relying on the user to have to write additional logic to be able to the factory.



来源:https://stackoverflow.com/questions/41637621/are-all-of-these-method-signatures-valid-for-simple-factory-pattern

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!