创建型设计模式 — 工厂模式

作者: Chase_stars | 来源:发表于2019-08-18 17:50 被阅读3次

成功的秘诀,在永不改变既定的目的。 — 卢梭

写在前面

本篇讲解工厂模式,分简单工厂模式工厂方法模式两部分,由浅入深更好的理解工厂模式。

简单工厂模式

简单工厂模式的定义:简单工厂模式也可以叫做静态工厂方法模式,由一个工厂对象决定创建哪一种产品类的实例对象。

简单工厂模式.jpg

工厂类(Factory):主要负责实现创建所有的产品对象的内部逻辑。工厂类的创建产品对象的方法可以被外界直接调用,创建所需要的产品对象。
抽象产品类(Product):是简单工厂模式创建的所有的产品对象的父类,它描述的是所有产品实例所共有的公共接口。
具体产品类(ProductA/B):是简单工厂模式的创建目标。

接下来通过一个例子认识简单工厂模式:

有一个工厂可以生产汽车和电脑,而生产出来的产品首先要通过检测才能投放到市场,所以每一种产品都需要检测,检测这个行为就是所有产品共有的。

1.抽象产品类

因为检测这个行为是所有产品共有的,但不同的产品检测过程是不一样的,所以创建抽象类,并持有一个抽象方法,交由产品类来具体实现检测过程。

/**
 * 抽象产品类
 */
public abstract class Product {

    // 该方法是所有产品类所共有的接口,由产品类具体实现
    public abstract void startTest();
}
2.具体产品类

因为这个工厂可以生产汽车和电脑,所以要创建一个汽车产品类和一个电脑产品类,并继承抽象产品类实现抽象方法,在方法中实现各自的检测过程。

/**
 * 汽车产品类
 */
public class Car extends Product {

    @Override
    public void startTest() {
        Log.d("Car", "开始检测Car");
    }
}

/**
 * 电脑产品类
 */
public class Computer extends Product {

    @Override
    public void startTest() {
        Log.d("Computer", "开始检测Computer");
    }
}
3.工厂类

现在来创建工厂类,用来生产汽车产品类和电脑产品类,想生产哪种产品由我们自己决定。

/**
 * 工厂类
 */
public class Factory {
    public static final String CAR = "car";
    public static final String COMPUTER = "computer";

    /**
     * 创建产品对象
     * @param product 想要的产品
     * @return 具体产品对象
     */
    public static Product createProduct(String product) {
        switch (product) {
            case CAR:
                return new Car();
            case COMPUTER:
               return new Computer();
                default:
                    break;
        }
        return null;
    }
}
4.创建产品

工厂类和产品类都有了,现在就让我们来生产产品,想要什么产品是由我们自己决定的,我们想生产汽车就生产汽车,我们想生产电脑就生产电脑。

/**
 * 客户端,也就是我们自己
 */
public class Client {

    public Client() {
        // 生产汽车并开始检测,检测通过方可投放到市场
        Product car = Factory.createProduct(Factory.CAR);
        car.startTest();

        // 生产电脑并开始检测,检测通过方可投放到市场
        Product computer = Factory.createProduct(Factory.COMPUTER);
        computer.startTest();
    }
}

简单工厂模式的使用场景:

  • 工厂类负责创建的对象很少。
  • 外界只需要知道传入工厂类的参数,无需关心创建的过程。

工厂方法模式

工厂方法模式的定义:定义一个用于创建对象的接口类,让其子类决定实例化哪个类。工厂方法模式使一个类的实例化延迟到其子类。

工厂方法模式.png

抽象产品类(IProduct):是工厂方法模式创建所有的产品对象的父类,它描述的是所有的产品实例所共有的公共接口。
具体产品类(ConcreteProductImpl):是工厂方法模式的创建目标。
抽象工厂类(IFactory):是工厂方法模式创建工厂对象的父类,它描述的是工厂实例创建产品实例的接口。
具体工厂类(ConcreteFactoryImpl):是工厂方法模式的工厂类。

为了与简单工厂模式形成对比,依然使用之前的例子:

有一个工厂可以生产汽车和电脑,而生产出来的产品首先要通过检测才能投放到市场,所以每一种产品都需要检测,检测这个行为就是所有产品共有的。但是考虑到市场竞争,不能一直生产这两种产品,需要迎合市场不断调整产品线,恰巧现在的手机市场很好,那么就生产手机。可是目前的生产线只能生产汽车和电脑,不能够满足生产需求,那么就需要对生产线进行调整,不仅能够生产汽车和电脑,也可以生产其他任何产品。

1.抽象产品类

因为检测这个行为是所有产品共有的,但不同的产品检测过程是不一样的,所以创建抽象类,并持有一个抽象方法,交由产品类来具体实现检测过程。

/**
 * 抽象产品类
 */
public abstract class Product {

    // 该方法是所有产品类所共有的接口,由产品类具体实现
    public abstract void startTest();
}
2.具体产品类

因为这个工厂可以生产汽车和电脑,现在为了迎合市场又要生产手机,所以要创建一个汽车产品类,一个电脑产品类和一个手机产品类,并继承抽象产品类实现抽象方法,在方法中实现各自的检测过程。

/**
 * 汽车产品类
 */
public class Car extends Product {

    @Override
    public void startTest() {
        Log.d("Car", "开始检测Car");
    }
}

/**
 * 电脑产品类
 */
public class Computer extends Product {

    @Override
    public void startTest() {
        Log.d("Computer", "开始检测Computer");
    }
}

/**
 * 手机产品类
 */
public class Phone extends Product {
    @Override
    public void startTest() {
        Log.d("Car", "开始检测Phone");
    }
}
3.抽象工厂类

因为目前的生产线只能生产汽车和电脑,不能够满足生产需求,需要对生产线进行调整,使生产线能够生产任何产品。

/**
 * 抽象工厂类
 */
public abstract class Factory {

    // 创建不同产品的接口,由其工厂子类实现
    public abstract <T extends Product> T createProduct(Class<T> clazz);
}
4.具体工厂类

目前的需求是使生产线可以生产任何产品,而不再局限于汽车和电脑了,所以若产品线有调整无需调整生产线。

/**
 * 具体工厂类
 */
public class ProductFactory extends Factory {
   
    private ProductFactory() {
        
    }
    
    public static ProductFactory createFactory() {
        return new ProductFactory();
    }

    @Override
    public <T extends Product> T createProduct(Class<T> clazz) {
        if (clazz == null) {
            throw new NullPointerException("Product cannot is null");
        }
        String className = clazz.getName();
        Product product = null;
        try {
            // 通过反射创建产品
            product = (Product) Class.forName(className).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return (T) product;
    }
}
5.创建产品

生产线已经从之前的只能生产汽车和电脑调整为可以生产任何产品,回到例子中,新增了手机产品,那么我们就来生产汽车,电脑和手机,若日后增减产品也无需调整生产线。

/**
 * 客户端,也就是我们自己
 */
public class Client {

    public Client() {
        // 创建工厂类
        ProductFactory factory = ProductFactory.createFactory();

        // 生产汽车并开始检测,检测通过方可投放到市场
        Product car = factory.createProduct(Car.class);
        car.startTest();

        // 生产电脑并开始检测,检测通过方可投放到市场
        Product computer = factory.createProduct(Computer.class);
        computer.startTest();

        // 生产手机并开始检测,检测通过方可投放到市场
        Product phone = factory.createProduct(Phone.class);
        phone.startTest();
    }
}

工厂方法模式的使用场景:

  • 工厂类负责创建的对象很多。
  • 外界只需知道创建的产品类,无需关心创建的过程。

总结

简单工厂模式和工厂方法模式的区别:

  • 相同点:外界根据参数获取相应的类实例,避免了实例化类,降低了耦合性。
  • 不同点:简单工厂模式的可生成的类型在编译期间就被确定了,如果要增加类型,就要修改工厂类,这违背了开放封闭原则。

简单工厂模式的工厂类需要知道所有可生成的类型,如果可生成的类型过多或则层次过多不适合使用简单工厂模式,这时工厂方法模式的优势就体现出来了。

相关文章

网友评论

    本文标题:创建型设计模式 — 工厂模式

    本文链接:https://www.haomeiwen.com/subject/hgsrsctx.html