工厂模式&构造函数中的可重写方法调用

时间:2013-11-12 13:43:32

标签: java factory-pattern

我从此链接获取了工厂模式示例:http://howtodoinjava.com/2012/10/23/implementing-factory-design-pattern-in-java/

然而,当我将代码复制到我自己的IDE中时,我收到一条警告,说我在构造函数中有一个可重写的方法调用。我明白这意味着什么,我只是认为工厂模式应该解决这个问题?教程有缺陷吗?我应该做些不同的事吗?

我只包含其中一种车型,只是为了节省我粘贴的代码数量:

班级Car

package FactoryPattern;

public abstract class Car {



    public Car(CarType model){
        this.model = model;
        arrangeParts();
    }

    private void arrangeParts(){
        //Do one time processing herer
    }

    //Do subclass level processing in this method

    protected abstract void construct();
    private CarType model = null;
    public CarType getModel(){
        return model;
    }

    public void setModel (CarType model){
        this.model = model;
    }


}

班级CarFactory

package FactoryPattern;


public class CarFactory {

    public static Car buildCar(CarType model){
        Car car = null;
        switch (model) {
            case SMALL:
                car = new SmallCar();
                break;
            case SEDAN:
                car = new SedanCar();
                break;
            case LUXURY:
                car = new LuxuryCar();
                break;
            default:
                //throw an exception
                break;        
        }
        return car;
    }    
}

班级FactoryPattern

package FactoryPattern;

public enum CarType {

    SMALL, SEDAN, LUXURY

}

package FactoryPattern;

public class LuxuryCar extends Car {

    LuxuryCar(){
        super(CarType.LUXURY);
        construct();
    }

    @Override
    protected void construct(){
        System.out.println("Building Luxury Car");
    }

}

班级CarFactoryTest

package FactoryPattern;

public class CarFactoryTest {
    public static void main(String[] args) {

        CarFactory.buildCar(CarType.SMALL);
        CarFactory.buildCar(CarType.SEDAN);
        CarFactory.buildCar(CarType.LUXURY);
    }

}

1 个答案:

答案 0 :(得分:1)

警告来自此处

LuxuryCar(){
    super(CarType.LUXURY);
    construct();
}

construct()方法为protected,因此可以在LuxuryCar的子类中覆盖。如果一个不知情的开发人员重写该方法并尝试使用尚未在父类中初始化的字段,那么很多事情都会变坏。这就是IDE警告你的原因。

例如,

public class LuxuryCar extends Car {
    protected Televesion tv;

    LuxuryCar(){
        super(CarType.LUXURY);
        construct(); // will call the overriden method in the sub class
    }

    @Override
    protected void construct(){
        tv = new Television();
    }
}

public class BetterLuxuryCar extends LuxuryCar {
    BetterLuxuryCar(){
        super();
    }

    @Override
    protected void construct(){
        tv.upgrade(); // oops NullPointerException
    }
}

请注意,像construct()这样的方法似乎属于Factory本身。此外,Car类不需要CarType字段,子类型已经知道它是什么类型。