成功的秘诀,在永不改变既定的目的。 — 卢梭
写在前面
本篇讲解工厂模式,分简单工厂模式和工厂方法模式两部分,由浅入深更好的理解工厂模式。
简单工厂模式
简单工厂模式的定义:简单工厂模式也可以叫做静态工厂方法模式,由一个工厂对象决定创建哪一种产品类的实例对象。
简单工厂模式.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();
}
}
工厂方法模式的使用场景:
- 工厂类负责创建的对象很多。
- 外界只需知道创建的产品类,无需关心创建的过程。
总结
简单工厂模式和工厂方法模式的区别:
- 相同点:外界根据参数获取相应的类实例,避免了实例化类,降低了耦合性。
- 不同点:简单工厂模式的可生成的类型在编译期间就被确定了,如果要增加类型,就要修改工厂类,这违背了开放封闭原则。
简单工厂模式的工厂类需要知道所有可生成的类型,如果可生成的类型过多或则层次过多不适合使用简单工厂模式,这时工厂方法模式的优势就体现出来了。
网友评论