工厂方法模式的介绍

工厂方法模式是一种结构简单的模式,并且在我们的应用中很广泛,如Android中Activity的各个生命周期的回调,以onCreate方法为例,它就可以看做是一个工厂方法,我们在其中构造我们的View并返回给framework处理。

工厂方法模式的定义

定义一个用于创建对象的接口,让子类决定实例化哪个类。

工厂方法模式的使用场景

在任何需要生成复杂对象的地方,都可以使用工厂方法模式。复杂对象适合使用工厂方法模式,用new就能完成创建的对象无需使用工厂方法模式。

工厂方法模式的类图

创建型设计模式之工厂方法模式-LMLPHP

角色介绍:

Factory - 抽象工厂,是工厂方法的核心

ConcreteFactory - 具体工厂,实现了业务逻辑

Product - 抽象产品,是工厂方法模式所创建的产品的父类

ConcreteProduct - 为实现抽象产品的某个具体产品

抽象工厂的简单实现

下面生产汽车为例,要生产三款汽车,于是使用一条生产线来生产,我们先定义产品,产品是汽车。

抽象汽车,即抽象产品

public abstract class Car {
    public abstract void drive();
}

接下来是具体的车型

奥迪汽车,即具体的产品类

public class AudiCar extends Car {
    @Override
    public void drive() {
        System.out.println("奥迪汽车开始启动啦!");
    }
}

奔驰汽车,即具体的产品类

public class BenzCar extends Car {

    @Override
    public void drive() {
        System.out.println("奔驰车开始启动啦!");
    }
}

宝马汽车,即具体的产品类

public class BWMCar extends Car {
    @Override
    public void drive() {
       System.out.println("宝马汽车开始启动啦!");
    }
}

有了产品就要有工厂来生产,定义一个汽车抽象工厂。

抽象汽车工厂,即抽象工厂角色

public abstract class CarFactory {
    public abstract Car createCar();
}

接下来是具体的车型工厂。

生产奥迪车的工厂,即具体工厂类

public class AudiCarFactory extends CarFactory {

    @Override
    public Car createCar() {
        return new AudiCar();
    }

}

生产奔驰车的工厂,即具体工厂类

public class BenzCarFactory extends CarFactory {
    @Override
    public Car createCar() {
        return new BenzCar();
    }
}

生产宝马车的工厂,即具体工厂类

public class BWMCarFactory extends CarFactory {
    @Override
    public Car createCar() {
        return new BWMCar();
    }
}

最后我们将各个汽车的生产组装成一条生产线。

客户端

public class Client {

    public static void main(String[] args){
        //制造各个工厂
        CarFactory audiFactory = new AudiCarFactory();
        CarFactory benzFactory = new BenzCarFactory();
        CarFactory bwmFactory = new BWMCarFactory();
        //生产各种车
        Car audiCar = audiFactory.createCar();
        Car benzCar = benzFactory.createCar();
        Car bwmCar = bwmFactory.createCar();
        //车启动
        audiCar.drive();
        benzCar.drive();
        bwmCar.drive();
    }

}

输出结果

奥迪汽车开始启动啦!
奔驰车开始启动啦!
宝马汽车开始启动啦!

可以看到我们需要哪种车型就可以定义哪种车型的具体工厂,像这样拥有多个工厂的的方式我们称之为多工厂模式,每个工厂各司其职。


但上面的方式不好的是会产生大量工厂,使代码臃肿,在实际开发中,我们可以使用反射的方式更加简洁的来生产具体的产品对象,此时需要在工厂方法的参数列表中传入一个Class类来决定是哪一个产品类。

使用反射的方式来生产具体的产品对象,抽象工厂角色

public abstract class CarFactory2 {

    /**
     * 抽象工厂方法,具体生产什么产品由子类决定
     */
    public abstract <T extends Car> T createCar(Class<T> car);

}

对于 具体的工厂,则通过反射获取类的实例即可

public class ConcreteCarFactory extends CarFactory2 {

    @Override
    public <T extends Car> T createCar(Class<T> car) {
        Car c = null;
        try {
            c = (T) Class.forName(car.getName()).newInstance();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return (T) c;
    }

}

客户端

public class Client {

    public static void main(String[] args){
        //创建工厂
        CarFactory2 carFactory = new ConcreteCarFactory2();
        //生产车
        AudiCar audiCar = carFactory.createCar(AudiCar.class);
        BenzCar benzCar = carFactory.createCar(BenzCar.class);
        BWMCar bwmCar = carFactory.createCar(BWMCar.class);
        //车启动
        audiCar.drive();
        benzCar.drive();
        bwmCar.drive();
    }
}

输出和和上面一样 

以上的方式,需要哪一个产品的对象,就传入哪一个产品的类的型即可,这种方式比较简洁,动态。


上面我们有三个工厂,如果我们只需要生产一种车型,即我们只有一个工厂时,我们就可以把抽象工厂简化掉,将对应的工厂方法改为静态方法,像下面,我们只生产一辆五菱车。

一个工厂,只生产一种产品

public class Factory {

    public static Car createWuLingCar(){
        return new WuLingCar();
    }

}

像这样的方式又称为简单工厂方式或静态工厂方式,它是工厂方式模式的一个弱化版本。


总结

工厂模式依赖于抽象的架构,将实例化的具体任务交给子类去完成,有非常好的扩展性。

优点:

将类的实例化逻辑交由工厂实现,实现代码模块之间的解耦

缺点:

每次为工厂模式添加新的产品时都要编写一个新的产品类,同时还要引入抽象层,回导致类结构的复杂


 
10-05 11:37