工厂方法模式 问题引入 问题描述 大学生薛磊风在过去三年里一直在帮助孤寡老人,每周都去老人家里,为老人洗衣扫地、买米买油。有一次,他不幸受了伤,便委托他的两个同学继续去帮助老人,且不必提及任何人的名字,只需说是学雷锋做好事即可。 帮助老人是长期工作,三名“学雷锋的大学生”毕业后,也依然会以“社区志愿者”的名义继续学雷锋做好事。而老人其实不需要知道是谁来做好事,只需要知道是学雷锋的人来帮助就可以了。 上述过程在程序实现时,我们如果使用“学雷锋的大学生”封装学雷锋者并调用,当他们毕业时,我们需要以“社区志愿者”重新封装,重新调用,要想使代码变更量少,可以用 来实现。 模式定义 是指定义一个用于创建对象的结构,让子类决定实例化哪个类。工厂方法使类的实例化过程延迟到其子类。
大学生薛磊风在过去三年里一直在帮助孤寡老人,每周都去老人家里,为老人洗衣扫地、买米买油。有一次,他不幸受了伤,便委托他的两个同学继续去帮助老人,且不必提及任何人的名字,只需说是学雷锋做好事即可。
帮助老人是长期工作,三名“学雷锋的大学生”毕业后,也依然会以“社区志愿者”的名义继续学雷锋做好事。而老人其实不需要知道是谁来做好事,只需要知道是学雷锋的人来帮助就可以了。
上述过程在程序实现时,我们如果使用“学雷锋的大学生”封装学雷锋者并调用,当他们毕业时,我们需要以“社区志愿者”重新封装,重新调用,要想使代码变更量少,可以用工厂方法模式来实现。
工厂方法模式(Factory Method Pattern)是指定义一个用于创建对象的结构,让子类决定实例化哪个类。工厂方法使类的实例化过程延迟到其子类。
工厂方法模式实现时,客户端需要决定实例化哪一个工厂来实现功能类,即将简单工厂内部的逻辑判断已到了客户端进行。
这一程序可以先用简单工厂模式实现,但由于学雷锋的学生毕业后,会转变身份成为社区志愿者,此时若使用简单工厂模式会涉及到工厂类的修改,违背开放封闭原则。当我们使用工厂方法模式时,可以对学雷锋的学生和社区志愿者分别建立工厂类,让客户端决定实例化哪一个工厂类。
此时可以考虑使用工厂方法模式来解决问题。
LetFeng,同时定义公共接口,即三种好事:
Sweep(),Wash(),BuyRice()。Undergraduate,及社区志愿者Volunteer,继承于抽象类LetFeng;IFactory,再定义学雷锋的大学生工厂UndergraduateFactory和社区志愿者工厂VolunteerFactory继承于雷锋工厂,用于创建具体的对象。此处我们使用Java语言来实现这一方案,C#语言实现可见原书原版,本项目的所有语言实现可见本项目Github仓库,其中包括:C++,Java,python,读者可按需参阅。
首先创建抽象类LetFeng。
public class LeiFeng { public void sweep() { System.out.println("Sweep"); } public void wash() { System.out.println("Wash"); } public void buyRice() { System.out.println("Buy rice"); } }
创建做好事的类,学雷锋的大学生Undergraduate,及社区志愿者Volunteer。
public class Undergraduate extends LeiFeng { } public class Volunteer extends LeiFeng { }
创建雷锋工厂类IFactory,再定义学雷锋的大学生工厂UndergraduateFactory和社区志愿者工厂VolunteerFactory
public interface IFactory { public LeiFeng createLeiFeng(); } public class UndergraduateFactory implements IFactory { @Override public LeiFeng createLeiFeng() { return new Undergraduate(); } } public class VolunteerFactory implements IFactory { @Override public LeiFeng createLeiFeng() { return new Volunteer(); } }
客户端如下。
public class FactoryMethodClient { public static void main(String[] args) { IFactory factory = new UndergraduateFactory(); LeiFeng student = factory.createLeiFeng(); student.buyRice(); student.sweep(); student.wash(); LeiFeng volunteer = new VolunteerFactory().createLeiFeng(); volunteer.buyRice(); volunteer.sweep(); volunteer.wash(); } }
运行结果如下。
买米 扫地 洗衣 买米 扫地 洗衣
工厂方法模式由三个主要角色组成:
工厂方法模式的通用结构示意图如下。

有明确的根据不同条件创造实例的计划时。将类类比为产品,产品具有系列/组合的形式,则使用者可以在不清楚类生产的具体过程及一个系列/组合的类包含的具体内容的情况下,使用一个系列的产品。
有以下几类适合场景
工厂方法模式的优点包括
工厂方法模式的缺点包括