课程咨询 :186 8716 1620      qq:2066486918

昆明Java培训 > 达内新闻 > Java程序建议:用枚举实现工厂方法模式更简洁
  • Java程序建议:用枚举实现工厂方法模式更简洁

    发布:昆明Java培训      来源:达内新闻      时间:2016-09-28

  • 昆明Java培训机构的老师今天给大家讲改善Java程序的建议

    建议88:用枚举实现工厂方法模式更简洁

    工厂方法模式(Factory Method Pattern)是"创建对象的接口,让子类决定实例化哪一个类,并使一个类的实例化延迟到其它子类"。工厂方法模式在我们的开发中经常会用到。下面昆明Java培训机构的老师以汽车制造为例,看看一般的工厂方法模式是如何实现 的,代码如下:

    1 //抽象产品

    2 interface Car{

    3    

    4 }

    5 //具体产品类

    6 class FordCar implements Car{

    7    

    8 }

    9 //具体产品类

    10 class BuickCar implements Car{

    11    

    12 }

    13 //工厂类

    14 class CarFactory{

    15    //生产汽车

    16    public static Car createCar(Class<? extends Car> c){

    17        try {

    18            return c.newInstance();

    19        } catch (InstantiationException | IllegalAccessException e) {

    20            e.printStackTrace();

    21        }

    22        return null;

    23    }

    24 }

    这是最原始的工厂方法模式,有两个产品:福特汽车和别克汽车,然后通过工厂方法模式来生产。有了工厂方法模式,我们就不用关心一辆车具体是怎么生成的了,只要告诉工厂"给我生产一辆福特汽车"就可以了,下面是产出一 辆福特汽车时客户端的代码:

    public static void main(String[] args) {

    //生产车辆

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

    }

    这就是我们经常使用的工厂方法模式,但经常使用并不代表就是最优秀、最简洁的。此处再介绍一种通过枚举实现工厂方法模式的方案,谁优谁劣你自行评价。枚举实现工厂方法模式有两种方法:

    (1)、枚举非静态方法实现工厂方法模式

    我们知道每个枚举项都是该枚举的实例对象,那是不是定义一个方法可以生成每个枚举项对应产品来实现此模式呢?代码如下:

    1 enum CarFactory {

    2    //定义生产类能生产汽车的类型

    3    FordCar, BuickCar;

    4    //生产汽车

    5    public Car create() {

    6        switch (this) {

    7        case FordCar:

    8            return new FordCar();

    9        case BuickCar:

    10            return new BuickCar();

    11        default:

    12            throw new AssertionError("无效参数");

    13        }

    14    }

    15

    16 }

    create是一个非静态方法,也就是只有通过FordCar、BuickCar枚举项才能访问。采用这种方式实现工厂方法模式时,客户端要生产一辆汽车就很简单了,代码如下:

    public static void main(String[] args) {

    //生产车辆

    Car car = CarFactory.BuickCar.create();

    }

    (2)、通过抽象方法生成产品

    枚举类型虽然不能继承,但是可以用abstract修饰其方法,此时就表示该枚举是一个抽象枚举,需要每个枚举项自行实现该方法,也就是说枚举项的类型是该枚举的一个子类,我们来看代码:

    1 enum CarFactory {

    2    //定义生产类能生产汽车的类型

    3    FordCar{

    4        public Car create(){

    5            return new FordCar();

    6        }

    7    },

    8    BuickCar{

    9        public Car create(){

    10            return new BuickCar();

    11        }

    12    };

    13    //抽象生产方法

    14    public abstract Car create();

    15 }

    首先定义一个抽象制造方法create,然后每个枚举项自行实现,这种方式编译后会产生CarFactory的匿名子类,因为每个枚举项都要实现create抽象方法。客户端调用与上一个方案相同,不再赘述。

    大家可能会问,为什么要使用枚举类型的工厂方法模式呢?那是因为使用枚举类型的工厂方法模式有以下三个优点:

    避免错误调用的发生:一般工厂方法模式中的生产方法(也就是createCar方法),可以接收三种类型的参数:类型参数(如我们的例子)、String参数(生产方法中判断String参数是需要生产什么产品)、int参数(根据int值判断需要生产什么类 的的产品),这三种参数都是宽泛的数据类型,很容易发生错误(比如边界问题、null值问题),而且出现这类错误编译器还不会报警,例如:

    public static void main(String[] args) {

    //生产车辆

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

    }

    Car是一个接口,完全合乎createCar的要求,所以它在编译时不会报任何错误,但一运行就会报出InstantiationException异常,而使用枚举类型的工厂方法模式就不存在该问题了,不需要传递任何参数,只需要选择好生产什么类型的产品 可。

    性能好,使用简洁:枚举类型的计算时以int类型的计算为基础的,这是最基本的操作,性能当然会快,至于使用便捷,注意看客户端的调用,代码的字面意思就是"汽车工厂,我要一辆别克汽车,赶快生产"。

    降低类间耦合:不管生产方法接收的是Class、String还是int的参数,都会成为客户端类的负担,这些类并不是客户端需要的,而是因为工厂方法的限制必须输入的,例如Class参数,对客户端main方法来说,他需要传递一个FordCar.class 数才能生产一辆福特汽车,除了在create方法中传递参数外,业务类不需要改Car的实现类。这严重违背了迪米特原则(Law of Demeter 简称LoD),也就是最少知识原则:一个对象应该对其它对象有最少的了解。

    而枚举类型的工厂方法就没有这种问题了,它只需要依赖工厂类就可以生产一辆符合接口的汽车,完全可以无视具体汽车类的存在。

    了解详情请登陆昆明达内Java培训官网(km.Java.tedu.cn)!

    推荐文章

上一篇:java中抽象、分装、继承和多态的理解

下一篇:Java程序建议:枚举项的数量限制在64个以内

最新开班日期  |  更多

Java--零基础全日制班

Java--零基础全日制班

开班日期:11/30

Java--零基础业余班

Java--零基础业余班

开班日期:11/30

Java--周末提升班

Java--周末提升班

开班日期:11/30

Java--零基础周末班

Java--零基础周末班

开班日期:11/30

  • 网址:http://km .java.tedu.cn      地址:昆明市官渡区春城路62号证券大厦附楼6楼
  • 课程培训电话:186 8716 1620      qq:2066486918    全国服务监督电话:400-827-0010
  • 服务邮箱 ts@tedu.cn
  • 2001-2016 达内国际公司(TARENA INTERNATIONAL,INC.) 版权所有 京ICP证08000853号-56