用枚举实现工厂方法模式更简洁?

《编写高质量代码java》建议88--用枚举实现工厂方法模式更简洁<质疑>java

 

建议先看下附录的代码,而后再看文字说明,附录代码展现了:原始工厂方法模式枚举实现的工厂方法模式程序员

做者(秦小波)认为用枚举实现工厂方法模式更简洁,主要缘由以下三点:ide

1.避免错误调用的发生,好比性能

Car car = CarFactory.createCar(Car.class);ui

这样的代码在编译时候不会报错,运行的时会报InstantiationException,我以为用枚举调用实例化的时候,程序员也要指定你调用的是BuickCar仍是FordCar,只是枚举作了下限定而已。spa

我认为良好的异常控制就能比较好的解决问题。并且通常动态加载类的时候,也是用Enum.valueof()方法定位枚举,也会所以抛出异常!code

 

2.性能好,使用便捷blog

枚举实现,还须要switch,虽然用ordinal()实现了int排序,不过我感受CarFactory.createCar(FordCar.class)连这个开销都没有吧?!排序

 

3.下降类间耦合it

用原始工厂模式做者认为,调用者须要传递一个FordCar.class参数才能生产一两福特汽车,可是用枚举方法的时候也是要指定枚举的值才能够调用,这个并没有太大区别。

主要我认为,若是新定义一种汽车,枚举的EnumCarFactory里就须要对应新加一个代码块,用来实现新加汽车的实例化,原始的工厂模式不须要变,只要新增的汽车类是extends Car!

 

你们也留言说说本身的想法吧。

 

附录:原始工厂方法模式和枚举实现的工厂方法模式

interface Car {
    public void myName();
};

class FordCar implements Car {
    public void myName() {
        System.out.println("it's ford");
    }
};

class BuickCar implements Car {
    public void myName() {
        System.out.println("it's buick");
    }
};

/**
 * 原始的工厂模式,新增一个Car子类,彻底无论
 */
class OriginCarFactory {
    public static Car createCar(Class<? extends Car> c) {
        try {
            return (Car) c.newInstance();
        } catch (Exception e) {
            System.out.println("无效参数,没法初始化");
        }
        return null;
    }
}

/**
 * 枚举实现工厂模式,一旦新加一个类,还须要在enum中新增对应实例化方法
 */
enum EnumCarFactory {
    FordCar {
        @Override
        public Car create() {
            return new FordCar();
        }        
    },
    BuickCar {
        @Override
        public Car create() {
            return new BuickCar();
        }        
    };

    //abstract修饰方法,强制每一个枚举实现该方法
    public abstract Car create();
}
public class Main {
    public static void main(String[] args) {
        
        //最经常使用的工厂模式,实例化class
        Car car = OriginCarFactory.createCar(BuickCar.class);
        if(car != null) {
            car.myName();
        }        
        
        //用枚举模式实例化class
        try {
            car = EnumCarFactory.valueOf("FordCar").create();
            car.myName();
        } catch (Exception e) {
            System.out.println("无效参数,没法初始化");
        }
        
    }
}
相关文章
相关标签/搜索