【设计模式笔记13】:工厂方法模式示例代码
·
工厂方法模式示例 (代码实现)
这个示例以生产电视机为例,完整地展示了工厂方法模式的四个角色是如何通过代码实现的。
a. 代码结构与实现分析


-
角色1: Product (抽象产品)
- 代码:
public abstract class Product { public abstract void productMethod(); } - 解析: 这里定义了一个抽象类
Product,它代表了所有产品的通用接口。在这个例子中,可以理解为“电视机”。它包含一个抽象方法productMethod(),可以理解为电视机的通用功能,比如“播放”。
- 代码:
-
角色2: ConcreteProduct (具体产品)
- 代码:
class ConcreteProduct extends Product { @Override public void productMethod() { System.out.println("海尔电视机播放中......"); } } - 解析:
ConcreteProduct类继承了Product抽象类,并实现了productMethod()方法。这代表一个具体的产品,即“海尔电视机”。当调用它的productMethod()时,它会执行自己特定的业务逻辑。
- 代码:
-
角色3: Creator (抽象工厂)
- 代码:
abstract class Creator { public abstract Product factoryMethod(); } - 解析: 这里定义了一个抽象工厂
Creator,它声明了一个核心的工厂方法factoryMethod()。这个方法的返回类型是抽象产品Product。它只负责定义创建产品的接口,但不负责实现,将具体的创建过程延迟到子类中。
- 代码:
-
角色4: ConcreteCreator (具体工厂)
- 代码:
class ConcreteCreator extends Creator { @Override public Product factoryMethod() { System.out.println("海尔电视机工厂生产海尔电视机。"); return new ConcreteProduct(); } } - 解析:
ConcreteCreator继承了抽象工厂Creator,并实现了factoryMethod()。它的职责非常明确:创建并返回一个具体的ConcreteProduct实例。在这个例子中,“海尔电视机工厂”(ConcreteCreator) 专门负责生产“海尔电视机”(ConcreteProduct)。
- 代码:
b. 客户端实现与模式精髓

图片描述:展示了
Client类的main方法,其中有两种创建Creator的方式,一种是直接new,另一种是被注释掉的、推荐使用的“XML+Java反射”方式。下方显示了程序的运行结果。
客户端 (Client) 的代码是理解工厂方法模式如何实现解耦和开闭原则的关键。
-
客户端职责: 客户端的目的是使用产品,而不是关心产品是如何被创建的。
-
实现方式一:直接实例化具体工厂 (不够灵活)
- 代码:
//面向抽象编程,提高了程序的灵活性;不使用“XML+Java反射”方式 Creator creator = new ConcreteCreator(); //可以选择其它的具体创建者 Product product = creator.factoryMethod(); //创建产品 product.productMethod(); //使用产品方法 - 解析:
- 客户端代码首先
new了一个具体工厂ConcreteCreator。 - 然后通过这个工厂实例调用
factoryMethod()来获得一个Product对象。 - 最后调用产品的
productMethod()方法。
- 客户端代码首先
- 总结: 这种方式虽然实现了产品创建和使用的分离(客户端只知道
Product接口,不知道ConcreteProduct),但客户端代码硬编码了new ConcreteCreator(),即客户端与具体工厂发生了耦合。如果现在需要换成“海信电视机工厂”,就必须修改客户端的这行代码,这在一定程度上还是违反了开闭原则。
- 代码:
-
实现方式二:XML配置文件 + Java反射 (推荐方式)
- 代码:
//推荐使用“XML配置文件+Java反射”方式 //当新增产品时,只需要同时创建具体产品类及相应的具体工厂类,并对配置文件做相应地修改 try { Creator creator = (Creator) XMLUtil.getBean(); //强制类型转换 Product product = creator.factoryMethod(); //调用抽象方法 product.productMethod(); //调用抽象方法 } catch (Exception e) { System.out.println(e.getMessage()); } - 解析:
- 这种方式是工厂方法模式的最佳实践。客户端代码中不再出现任何具体工厂的类名。
- 具体使用哪个工厂,是由一个外部的XML配置文件来决定的。例如,XML文件中可能写着
<className>com.example.ConcreteCreator</className>。 XMLUtil.getBean()方法(一个辅助工具类)会读取这个XML文件,获取其中配置的类名字符串。- 然后,它利用Java的反射机制,根据这个字符串动态地创建该类的实例。
- 客户端代码拿到这个实例后,向上转型为抽象工厂
Creator,然后就可以正常使用了。
- 总结: 这是实现开闭原则的终极形态。如果现在需要将“海尔电视机”换成“海信电视机”,我们只需要:
- 新增
HisenseProduct类和HisenseCreator类。 - 只修改XML配置文件中的类名为
com.example.HisenseCreator。 - 客户端的
Client.java代码完全不需要任何修改,甚至不需要重新编译。
这使得系统在扩展新产品时,真正做到了对修改关闭,对扩展开放。
- 新增
- 代码:
-
运行结果分析
海尔电视机工厂生产海尔电视机。— 这是ConcreteCreator的factoryMethod被调用时打印的。海尔电视机播放中......— 这是Client在获得Product对象后,调用其productMethod时打印的。- 这个结果清晰地展示了“先由具体工厂创建产品,再由客户端使用产品”的完整流程。
更多推荐

所有评论(0)