标准 专业
多元 极客

设计模式实验室(16)——工厂模式

什么是工厂方法模式?

工厂方法模式是一种创建型设计模式。

工厂方法模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中,核心工厂类不再负责产品创建,这样核心类成为一个抽象工厂的角色,仅负责具体工厂子类必须实现的接口,这样做的好处是系统可以在不修改具体工厂角色的情况下,添加新产品。

工厂模式在实际开发中应用很广,比如Spring的Bean工厂。举个例子,如果在一个系统中,我们需要连接多种种类的数据库,在系统架构设计时,我们通常把数据库连接这部分分离开来。而在获取数据库连接时,我们可以通过工厂方法模式获取相应的数据库连接,其实,Spring也是用这种方法进行连接管理。

核心结构

  • Product。抽象产品,它定义了产品的接口,是具体产品角色的公共父类。
  • ConcreteProduct。具体产品,它实现了抽象产品接口,具体产品由具体工厂创建,一一对应。
  • Factory。抽象工厂,它定义了工厂方法,并返回一个产品,是工厂方法模式的核心,所有的具体工厂方法都必须实现抽象工厂,抽象工厂既可以是接口,又可以是抽象类。
  • ConcreteFactory。具体工厂,它是抽象工厂的子类,实现了抽象工厂方法中定义的工厂方法,调用者可以调用这个方法来获取产品实例。

类图展示

工厂方法模式

代码分析

在工厂方法模式中,我们将对简单工厂模式的示例进行优化。

首先我们还是创建抽象产品角色——推送人群:

/**
 * Created by <sunshine> mysunshinedreams@163.com on 2017/1/12 0012.
 * 工厂模式——抽象产品
 */
public abstract class Group {

	public void before() {
		System.out.println("Selecting group...");
	}

	public void after() {
		System.out.println("done");
	}

	public abstract void select();
}

接着,我们创建具体产品角色——还是一样的配方,还是一样的味道:

青少年人群:

/**
 * Created by <sunshine> mysunshinedreams@163.com on 2017/1/12 0012.
 * 工厂模式——具体产品
 */
public class TeenageGroup extends Group {
	@Override
	public void select() {
		System.out.println("focus on teenagers");
	}
}

成年人群:

/**
 * Created by <sunshine> mysunshinedreams@163.com on 2017/1/12 0012.
 * 工厂模式——具体产品
 */
public class AdultGroup extends Group {
	@Override
	public void select() {
		System.out.println("focus on adult");
	}
}

年长人群:

/**
 * Created by <sunshine> mysunshinedreams@163.com on 2017/1/12 0012.
 * 工厂模式——具体产品
 */
public class ElderGroup extends Group {
	@Override
	public void select() {
		System.out.println("focus on elder");
	}
}

接下来写工厂方法模式的核心。

我们需要定义一个抽象工厂:

/**
 * Created by <sunshine> mysunshinedreams@163.com on 2017/1/12 0012.
 * 工厂模式——抽象工厂
 */
public abstract class GroupFactory {

	public abstract Group getGroup();
}

根据不同的具体产品,我们将为其创建专属生产工厂。

青少年人群生产工厂:

/**
 * Created by <sunshine> mysunshinedreams@163.com on 2017/1/12 0012.
 * 工厂模式——具体工厂
 */
public class TeenageGroupFactory extends GroupFactory {
	@Override
	public Group getGroup() {
		return new TeenageGroup();
	}
}
/**
 * Created by <sunshine> mysunshinedreams@163.com on 2017/1/12 0012.
 * 工厂模式——具体工厂
 */
public class AdultGroupFactory extends GroupFactory {
	@Override
	public Group getGroup() {
		return new AdultGroup();
	}
}
/**
 * Created by <sunshine> mysunshinedreams@163.com on 2017/1/12 0012.
 * 工厂模式——具体工厂
 */
public class ElderGroupFactory extends GroupFactory {
	@Override
	public Group getGroup() {
		return new ElderGroup();
	}
}

完活,上测试用例:

/**
 * Created by <sunshine> mysunshinedreams@163.com on 2017/1/12 0012.
 * 工厂模式测试
 */
public class FactoryTest {

    public static void main(String[] args) {
        factoryTest();
    }

	private static void factoryTest() {
        try {
            GroupFactory factory = null;
            Group group = null;
            factory = new TeenageGroupFactory();
            group = factory.getGroup();
            group.before();
            group.select();
            group.after();
            factory = new AdultGroupFactory();
            group = factory.getGroup();
            group.before();
            group.select();
            group.after();
            factory = new ElderGroupFactory();
            group = factory.getGroup();
            group.before();
            group.select();
            group.after();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

模式总结

优点

  • 外部调用方无需关心产品生产细节,甚至无需知道产品类名,只需知道生产产品的具体工厂角色即可。
  • 新增产品无需修改原有代码,仅仅添加新增具体产品角色和对应的具体工厂角色即可。
  • 产品角色和工厂角色的多态性设计是工厂方法模式的关键,它能够个性化生产产品对象,创建对象的细节完全封装在具体工厂内部。

缺点

  • 添加新产品时,需要添加新的产品角色和新的生产工厂,系统中类的个数将成对增加,提高了系统的复杂性。
  • 由于大量使用了多态特性,增加了系统的抽象性和理解难度,在一定程度上增加了业务实现难度。

适用场景

  • 外部调用不关心对象的创建细节,仅需获取对象。
赞(0) 投币

评论 抢沙发

慕勋的实验室慕勋的研究院

码字不容易,路过请投币

支付宝扫一扫

微信扫一扫