工厂模式总结
工厂模式总结
1. 背景与意义
- 在 Java 中,对象的创建通常通过
new
关键字完成,但这样会导致耦合严重。 - 如果需要替换或扩展对象,必须修改大量代码,违反了 开闭原则(对扩展开放、对修改关闭)。
- 工厂模式通过将对象创建与使用分离,实现了解耦,提高了代码的扩展性和维护性。
示例
public class CoffeeStore {public static void main(String[] args) {Coffee coffee = orderCoffee("latte");System.out.println(coffee.getName());}public static Coffee orderCoffee(String type){Coffee coffee = null;if("american".equals(type)){coffee = new AmericanCoffee();}else if ("latte".equals(type)){coffee = new LatteCoffee();}//添加配料coffee.addMilk();coffee.addSuqar();return coffee;}}
2. 简单工厂模式(Simple Factory)
概念
- 又称静态工厂模式。
- 由一个工厂类统一管理对象的创建。
结构
- 抽象产品:产品的接口或抽象类(如
Coffee
)。 - 具体产品:实现抽象产品的子类(如
LatteCoffee
、AmericanCoffee
)。 - 工厂类:根据传入参数返回不同的具体产品实例。
示例
// 抽象产品
public abstract class Coffee {public abstract String getName();public void addMilk() {System.out.println("加牛奶");}public void addSugar() {System.out.println("加糖");}
}// 具体产品
public class AmericanCoffee extends Coffee {public String getName() { return "美式咖啡"; }
}public class LatteCoffee extends Coffee {public String getName() { return "拿铁咖啡"; }
}// 简单工厂
public class SimpleCoffeeFactory {public static Coffee createCoffee(String type) {if ("american".equalsIgnoreCase(type)) {return new AmericanCoffee();} else if ("latte".equalsIgnoreCase(type)) {return new LatteCoffee();}return null;}
}// 咖啡店
public class CoffeeStore {public Coffee orderCoffee(String type) {Coffee coffee = SimpleCoffeeFactory.createCoffee(type);coffee.addMilk();coffee.addSugar();return coffee;}public static void main(String[] args) {CoffeeStore store = new CoffeeStore();Coffee c1 = store.orderCoffee("american");System.out.println("顾客点了: " + c1.getName());Coffee c2 = store.orderCoffee("latte");System.out.println("顾客点了: " + c2.getName());}
}
优缺点
✅ 优点
- 封装了对象创建过程,客户端只需传参即可获得对象。
- 对象创建与业务逻辑分离,便于管理。
❌ 缺点
- 增加新产品时,必须修改工厂类代码,违背了开闭原则。
3. 工厂方法模式(Factory Method)
概念
- 定义一个创建对象的接口,让子类决定实例化哪个产品。
- 将对象的实例化延迟到子类工厂中完成。
结构
- 抽象工厂(Factory):定义创建产品的接口。
- 具体工厂(Concrete Factory):实现接口,生产具体产品。
- 抽象产品(Product):定义产品规范。
- 具体产品(Concrete Product):实现抽象产品。
示例
// 抽象工厂
public interface CoffeeFactory {Coffee createCoffee();
}// 具体工厂
public class AmericanCoffeeFactory implements CoffeeFactory {public Coffee createCoffee() { return new AmericanCoffee(); }
}public class LatteCoffeeFactory implements CoffeeFactory {public Coffee createCoffee() { return new LatteCoffee(); }
}// 咖啡店
public class CoffeeStore {private CoffeeFactory factory;public CoffeeStore(CoffeeFactory factory) {this.factory = factory;}public Coffee orderCoffee() {Coffee coffee = factory.createCoffee();coffee.addMilk();coffee.addSugar();return coffee;}public static void main(String[] args) {CoffeeStore store1 = new CoffeeStore(new AmericanCoffeeFactory());Coffee c1 = store1.orderCoffee();System.out.println("顾客点了: " + c1.getName());CoffeeStore store2 = new CoffeeStore(new LatteCoffeeFactory());Coffee c2 = store2.orderCoffee();System.out.println("顾客点了: " + c2.getName());}
}
优缺点
✅ 优点
- 新增产品时,只需添加新的产品类和对应工厂类,不修改已有代码,符合开闭原则。
- 客户端只需知道工厂类,无需关心产品创建细节。
❌ 缺点
- 每增加一个产品,就要增加一个工厂,类数量增多,系统复杂度提升。
4. 抽象工厂模式(Abstract Factory)
概念
- 工厂方法模式的升级版。
- 一个工厂可以生产多个等级的产品(即产品族)。
- 用于创建一组相关或相互依赖的对象,而无需指定具体类。
结构
- 抽象工厂:定义多个创建产品的方法。
- 具体工厂:实现抽象工厂,负责创建某一产品族。
- 抽象产品:多个抽象产品接口。
- 具体产品:具体实现类。
示例
- 产品族:美式风味、意大利风味
- 产品等级:咖啡、甜点
// ===== 抽象产品 =====
public interface Coffee {String getName();void addMilk();void addSugar();
}public interface Dessert {String getName();
}// ===== 具体产品 =====
public class AmericanCoffee implements Coffee {public String getName() { return "美式咖啡"; }public void addMilk() { System.out.println("美式咖啡加牛奶"); }public void addSugar() { System.out.println("美式咖啡加糖"); }
}public class LatteCoffee implements Coffee {public String getName() { return "拿铁咖啡"; }public void addMilk() { System.out.println("拿铁咖啡加牛奶"); }public void addSugar() { System.out.println("拿铁咖啡加糖"); }
}public class Tiramisu implements Dessert {public String getName() { return "提拉米苏"; }
}public class MatchaMousse implements Dessert {public String getName() { return "抹茶慕斯"; }
}// ===== 抽象工厂 =====
public interface DessertFactory {Coffee createCoffee();Dessert createDessert();
}// ===== 具体工厂(产品族)=====
public class AmericanDessertFactory implements DessertFactory {public Coffee createCoffee() { return new AmericanCoffee(); }public Dessert createDessert() { return new MatchaMousse(); }
}public class ItalianDessertFactory implements DessertFactory {public Coffee createCoffee() { return new LatteCoffee(); }public Dessert createDessert() { return new Tiramisu(); }
}// ===== 客户端 =====
public class CoffeeStore {private DessertFactory factory;public CoffeeStore(DessertFactory factory) {this.factory = factory;}public void orderSet() {Coffee coffee = factory.createCoffee();Dessert dessert = factory.createDessert();coffee.addMilk();coffee.addSugar();System.out.println("顾客点了: " + coffee.getName() + " + " + dessert.getName());}public static void main(String[] args) {CoffeeStore americanStore = new CoffeeStore(new AmericanDessertFactory());americanStore.orderSet();CoffeeStore italianStore = new CoffeeStore(new ItalianDessertFactory());italianStore.orderSet();}
}
优缺点
✅ 优点
- 保证了同一产品族的对象一起工作,不会出现风格不统一的问题。
- 符合开闭原则,新增产品族时无需修改原有代码。
❌ 缺点
- 如果要在产品族中增加一个新产品(如“果汁”),所有工厂类都需要修改,扩展性差。
5. 使用场景对比
模式 | 特点 | 适用场景 |
---|---|---|
简单工厂 | 由一个工厂统一管理对象创建,逻辑集中 | 产品种类少,变化不频繁 |
工厂方法 | 每个工厂负责创建一种产品,符合开闭原则 | 需要频繁扩展产品,但产品族单一 |
抽象工厂 | 一个工厂生产多个等级的产品,产品族统一 | 需要创建多个相互关联的产品族 |
👉 总结一句话:
- 简单工厂:方便,但违反开闭原则。
- 工厂方法:扩展友好,但类数量多。
- 抽象工厂:适合生产一整套产品族,但扩展产品等级困难。