github.com/YaYiXiBa/Ja... 欢迎去看我的代码哦。。。
highlight: a11y-dark
1. 简单工厂模式 (Simple Factory)
优点:
- 实现简单:结构简单,易于理解和实现
缺点:
- 违反开闭原则:增加新产品需要修改工厂类逻辑
- 职责过重:工厂类集中了所有产品的创建逻辑
- 扩展性差:当产品类型较多时,工厂方法会变得臃肿 首先,先尝试实现以下类图:

typescript
//工厂类
public class SimpleFactory {
public static Shape getShape(String shapeType) {
if (shapeType.equalsIgnoreCase("Square")) {
return new Square();
}else if (shapeType.equalsIgnoreCase("Circle")) {
return new Circle();
}else if (shapeType.equalsIgnoreCase("Triangle")) {
return new Trangle();
}else{
return null;
}
}
}
//客户端
public class Client {
public static void main(String[] args) {
Shape square = SimpleFactory.getShape("Square");
assert square != null;
square.draw();
}
}
//运行结果
Drawing Square
Process finished with exit code 0
简单工厂模式存在,却又经常被说是不算严格的设计模式。为什么呢? 看一下类图:我们就是将手动new对象的方法进行了封装,把他们都放在了一个类中,作为静态方法getShape(String shapeType) 来调用。所以说,他简单。同时也带来了前文所述的缺点。

2. 工厂方法模式 (Factory Method)
先看图,其实可以去自己尝试实现一下。
这是一个使用手机工厂和电脑工厂实现生产产品的例子。很形象,但是建议注意细节:
- Product是所有产品类都要实现的接口,里面有一个展示功能的方法showFunction()。如此一来,任何工厂产出的物品就得到了统一,不管是生产手机,还是生产电脑,都可以返回Product。
- 手机工厂里的生产步骤是new Phone(),电脑工厂是new PC()。Phone和PC都实现了Product接口,都可以作为Product返回。
- 既然所有工厂都是在生产Product,不妨就把createProduct方法抽象出来,放在Factory接口中,要求所有的实际工厂都要实现这个接口。
先贴出部分代码,后续会给出github链接:
java
public interface Product {
public void showFunction();
}
public interface Factory {
public Product createProduct();
}
public class PCFactory implements Factory{
@Override
public Product createProduct() {
return new PersonalComputer();
}
}
public class Phone implements Product{
@Override
public void showFunction() {
System.out.println("手机可以打电话");
}
}
public class Client {
public static void main(String[] args) {
Factory pcFactory = new PCFactory();
Product pc = pcFactory.createProduct();
pc.showFunction();
PhoneFactory phoneFactory = new PhoneFactory();
Product phone = phoneFactory.createProduct();
phone.showFunction();
}
}
优点:
- 符合开闭原则:增加新产品只需添加新的工厂子类,无需修改现有代码
- 单一职责原则:每个具体工厂只负责创建一种产品
- 灵活性高:可以形成基于继承的等级结构
- 解耦彻底:客户端只需要知道抽象工厂和抽象产品
缺点:
- 类数量增加:每增加一个产品就需要增加一个具体工厂类
- 复杂性增加:引入了抽象层,增加了系统的抽象性和理解难度
- 需要额外开销:需要编写更多的类和接口
3. 抽象工厂模式 (Abstract Factory)
如果你彻底理解了工厂模式,那么抽象工厂很容易理解了。重点在于"抽象"二字。先看一下类图(哎,自己电脑装的是社区版生成不了diagram凑合看下吧。。。)
给出几个factory的代码,带着问题看:
- 创建产品的方式:public Color getColor(String colorName)、public Product getProduct(String productName)。Color和Product都是产品。这不是又回到了简单工厂的方式吗?在方法工厂中我们是使用单独的工厂来创建单独的产品。但抽象工厂面向的场景是,生产一组具有相互依赖关系的产品。比如各种"颜色"和各种电子产品。"红色"的"手机"和"黑色"的"手表",我们将其视为两组产品,他们之间是具有绑定关系的产品。试想,现在我现在就要生产"红色"的"手机"和"黑色"的"手表"。如果按照工厂方法的方式,在客户端,是不是要new四个工厂,分别生产四种对象。所以在这种场景下,如果将"电子设备"和"颜色"独立开,让ColorFactory和ProductFactory分别负责一类产品的生产,在客户端的操作就更方便一些。
- 关于"抽象":现在两个工厂的职责已经分开了,但是在客户端(也就是图中的AbstractFactoryParttenDemo,代码里我直接写的Client)与实际工厂之间仍然加了一层抽象,也就是抽象工厂。这里的目的在于让客户端代码只依赖抽象接口,让"解耦"更加彻底。这样即使工厂在创建产品的过程中发生了步骤上的变化,客户端的代码也不需要改动,因为引入的只是工厂实现类的上层抽象。注意看客户端的两行代码:
Factory colorFactory = FactoryProducer.getFactory("ColorFactory");
Factory productFactory = FactoryProducer.getFactory("ProductFactory");在客户端看来,管你是什么工厂实现类,我都按照Factory类来接受,然后给你一个局部变量则我这边做个标识就可以了。这样哪怕你有一天不叫ColorFactory了,改成"ColorMakeFactory"或者换了别的工厂来生产某个产品都无所谓。
3.为什么还有FactoryProducer:这里的逻辑其实就是在根据名称返回具体的实现类对吧? "名称"是客户端传来的,那么new出实际的工厂应该是谁来负责呢?肯定不能交给客户端吧。当然是属于我们提供给客户端的入口。客户端只需要调用FactoryProducer的getFactory方法就可以到到想要的工厂,这就叫做"无需关心具体的实现"。
csharp
public abstract class Factory {
public abstract Product getProduct(String productName);
public abstract Color getColor(String colorName);
}
scala
public class ColorFactory extends Factory{
@Override
public Product getProduct(String productName) {
return null;
}
@Override
public Color getColor(String colorName) {
if(Objects.equals(colorName, "red")){
return new Red();
}else if(colorName.equals("black")){
return new Black();
}else if (colorName.equals("yellow")){
return new Yellow();
}
return null;
}
}
scala
public class ProductFactory extends Factory{
@Override
public Product getProduct(String productName) {
if(productName.equals("PC")){
return new PC();
}else if(productName.equals("Phone")){
return new Phone();
}else if(productName.equals("Watch")){
return new Watch();
}
return null;
}
@Override
public Color getColor(String colorName) {
return null;
}
}
csharp
public class FactoryProducer {
public static Factory getFactory(String factoryName){
if(factoryName.equals("ColorFactory")){
return new ColorFactory();
} else if (factoryName.equals("ProductFactory")) {
return new ProductFactory();
}else{
throw new RuntimeException("名称有误");
}
}
}
ini
public class Client {
public static void main(String[] args) {
Factory colorFactory = FactoryProducer.getFactory("ColorFactory");
Factory productFactory = FactoryProducer.getFactory("ProductFactory");
Color red = colorFactory.getColor("red");
Product watch = productFactory.getProduct("Watch");
red.showColor();
watch.showFunction();
Color yellow = colorFactory.getColor("yellow");
Product phone = productFactory.getProduct("Phone");
yellow.showColor();
phone.showFunction();
}
}
运行结果:
红色
手表可以装*
黄色
手机可以打电话
Process finished with exit code 0
优点:
- 产品族支持:能创建一组相关或依赖的对象
- 一致性保证:保证客户端始终只使用同一个产品族中的对象
- 开闭原则:易于扩展产品族,增加新的产品族很方便
- 解耦彻底:客户端与具体类实现分离
缺点:
- 扩展产品等级困难:增加新产品需要修改抽象工厂接口及所有具体工厂类
- 类数量激增:支持的产品族和产品等级越多,系统越复杂
- 设计复杂:需要精心设计接口,否则难以应对变化
对比总结
模式 | 创建对象方式 | 扩展新产品 | 扩展新产品族 | 适用场景 |
---|---|---|---|---|
简单工厂 | 集中创建 | 修改工厂类 | 不支持 | 对象较少,变化不大 |
工厂方法 | 子类创建 | 添加子类 | 不支持 | 单一产品,需要灵活扩展 |
抽象工厂 | 产品族创建 | 修改接口 | 添加子类 | 相关产品族,强调一致性 |
选择建议:
- 当产品类型较少且不经常变化时,使用简单工厂
- 当需要灵活创建单一产品时,使用工厂方法
- 当需要创建一组相关产品时,使用抽象工厂 github.com/YaYiXiBa/Ja... 欢迎去看我的代码哦。。。