一、模式简介
工厂模式是java中很常用的设计模式之一。工厂模式类型的设计模式属于创建型模式,其本质就是将创建对象的代码给封装起来从而避免代码的重复并且可以达到客户端代码与具体类解耦合的效果。工厂设计模式主要分为:简单工厂、工厂方法、抽象工厂三种,下面将对三种模式详细介绍。
二、模式详解
简单工厂
简单工厂其实并不是一个模式,反而是一种良好的编程习惯,由于被经常使用,所以可能会被误认为工厂模式。简单工厂通过工厂类拥有的一个create(创建)方法通过不同的参数来实例化出某类实例的不同实例。
通过图片我们可以观察到通过简单的工厂可以创建出某类产品不同的产品,那如果想要新增一个产品,是不是需要去修改工厂类的代码呢?因此简单工厂不符合开闭原则,这也是简单工厂的一大缺点。(ps:Spring IOC通过配置文件+反射解决)
工厂方法
工厂方法模式定义了一个创建对象的接口,由工厂子类决定要实例化类是哪一个。工厂方法让类的实例化推迟到子类。
工厂方法通过子类实现工厂方法的方式去创建实例,当把某一类/某一种产品交由一个工厂生产,当新增产品时只需要增加生产这类产品的工厂即可,也符合了开闭原则和依赖倒置原则。但是需要多种产品相互组合生产时,工厂方法模式却无能为力。
抽象工厂
抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。 例如:水果代表一类产品、饮料代表另一类产品,通过抽象工厂就可以同时生产这两类产品。
我们可以发现其实工厂方法潜伏在抽象工厂之中,接口内每一个方法都负责创建一个具体的产品,同时我们利用抽象工厂的子类来提供这具体的做法。
-
三种形式对比总结
- 简单工厂 : 使用一个工厂对象用来生产同一等级结构中的任意产品。(不支持拓展增加产品)
- 工厂方法 : 使用多个工厂对象用来生产同一等级结构中对应的固定产品。(支持拓展增加产品)
- 抽象工厂 : 使用多个工厂对象用来生产不同产品族的全部产品。(不支持拓展增加产品;支持增加产品族)
三、代码示例
简单工厂
- 产品
public interface Product {
void product();
}
- 产品实例
public class ProductA implements Product{
@Override
public void product() {
System.out.println("I'm productA");
}
}
public class ProductB implements Product{
@Override
public void product() {
System.out.println("I'm productB");
}
}
- 简单工厂
public class SimpleFactory {
public static Product create(String type){
if ("ProductA".equals(type)){
return new ProductA();
}else if ("ProductB".equals(type)){
return new ProductA();
}else {
return null;
}
}
}
工厂方法
- 产品
public interface Product {
void product();
}
- 产品实例
public class ProductA implements Product{
@Override
public void product() {
System.out.println("I'm productA");
}
}
public class ProductB implements Product{
@Override
public void product() {
System.out.println("I'm productB");
}
}
- 工厂方法类(抽象)
public abstract class FactoryMethod {
public abstract Product create();
}
- 子工厂
public class FactoryA extends FactoryMethod{
@Override
public Product create() {
return new ProductA();
}
}
public class FactoryB extends FactoryMethod{
@Override
public Product create() {
return new ProductB();
}
}
抽象工厂
为区分两类产品,分别以“水果”和“饮料”作为两类产品,为节省代码空间这里不列出。
- 抽象工厂
public abstract class AbstractFactory {
/**
* 创建水果类产品
*
* @return {@link Fruit}
*/
public abstract Fruit createA();
/**
* 创建饮料类
*
* @return {@link Beverages}
*/
public abstract Beverages createB();
}
- 子工厂
public class FactoryA extends AbstractFactory{
@Override
public Fruit createA() {
//创建苹果
return new Apple();
}
@Override
public Beverages createB() {
//创建雪碧
return new Sprite();
}
}
public class FactoryB extends AbstractFactory{
@Override
public Fruit createA() {
//创建葡萄
return new Grape();
}
@Override
public Beverages createB() {
//创建可乐
return new Coke();
}
}
四、适用场景
工厂模式在平时的使用中较为广泛,下面列举出一些适用场景:
-
当你在编写代码的过程中,如果无法预知对象确切类别及其依赖关系时,可使用工厂方法。
-
如果你希望复用现有对象来节省系统资源,而不是每次都重新创建对象,可使用工厂方法。
-
如果代码需要与多个不同系列的相关产品交互,但是由于无法提前获取相关信息, 或者出于对未来扩展性的考虑,你不希望代码基于产品的具体类进行构建,在这种情况下,你可以使用抽象工厂。