工厂方法模式
针对简单工厂模式案例中的缺点,使用工厂方法模式就可以完美的解决,完全遵循开闭原则。
简单工厂模式只有一个工厂类,负责创建所有产品,如果要添加新的产品,就需要修改工厂类的代码。而工厂方法模式引入了抽象工厂和具体工厂的概念,每个具体工厂只负责创建一种具体的产品,添加新产品只需要添加新的工厂而无需修改原来的代码。这样使得产品的生产更灵活,扩展性更强,符合开闭原则。
结构
工厂方法模式分为以下几个角色:
- 抽象工厂(Abstract Factory):提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法来创建产品
- 具体工厂(Concrete Factory):主要是实现抽象工厂中的抽象方法,完成具体产品的创建
- 抽象产品(Abstract Product):定义了产品的规范,描述了产品的主要特性和功能
- 具体产品(Abstract Product):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应
实现
抽象咖啡工厂:
public interface CoffeeFactory {// 创建咖啡对象的方法Coffee createCoffee();
}
美式咖啡工厂:
public class AmericanCoffeeFactory implements CoffeeFactory {@Overridepublic Coffee createCoffee() {return new AmericanCoffee();}
}
拿铁咖啡工厂:
public class LatteCoffeeFactory implements CoffeeFactory {@Overridepublic Coffee createCoffee() {return new LatteCoffee();}
}
咖啡类:
public abstract class Coffee {// 获取咖啡名public abstract String getName();// 加糖public void addSugar(){System.out.println("加糖");}// 加奶public void addMilk(){System.out.println("加奶");}
}
美式咖啡类:
public class AmericanCoffee extends Coffee {@Overridepublic String getName() {return "美式咖啡";}
}
拿铁咖啡类:
public class LatteCoffee extends Coffee {@Overridepublic String getName() {return "拿铁咖啡";}
}
咖啡店类:
public class CoffeeStore {private CoffeeFactory coffeeFactory;public void setCoffeeFactory(CoffeeFactory coffeeFactory) {this.coffeeFactory = coffeeFactory;}// 点咖啡public Coffee orderCoffee(String type) {Coffee coffee = coffeeFactory.createCoffee();coffee.addMilk();coffee.addSugar();return coffee;}
}
测试:
public class Client {public static void main(String[] args) {// 创建对象CoffeeStore coffeeStore = new CoffeeStore();// 拿铁咖啡美式咖啡
// CoffeeFactory coffeeFactory = new AmericanCoffeeFactory();// 拿铁咖啡CoffeeFactory coffeeFactory = new LatteCoffeeFactory();coffeeStore.setCoffeeFactory(coffeeFactory);// 点咖啡Coffee coffee = coffeeStore.orderCoffee("Latte");System.out.println(coffee.getName());}
}
总结
可以看出,要增加产品类时也要相应的增加工厂类,不需要修改工厂类的代码,这样就解决了简单工厂模式的缺点(违反开闭原则)。
工厂方法模式是简单工厂模式的进一步抽象,由于使用了多态性,工厂方法模式保持了简单工厂模式的优点,并且解决了它的缺点。
优点:
- 用户只需要知道具体工厂的名称就可得到需要的产品,不管产品的具体创建过程
- 在系统增加新产品时只需要添加具体的产品类和对应的工厂类,无需对原工厂进行任何修改,符合开闭原则
缺点:
- 每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,增加了系统复杂度
应用场景
工厂方法模式使得每个工厂类的职责单一,每个工厂只负责创建一种产品,当创建对象涉及一系列复杂的初始化逻辑,而这些逻辑在不同的子类中可能有所不同时,可以使用工厂方法模式将这些初始化逻辑封装在子类中。如:
- Spring框架中的Bean工厂:通过配置文件或者注解,Spring可以根据配置文件动态的创建和管理对象
- JDBC中的Connection工厂:在Java数据库连接中,DriverManager使用工厂方法模式来创建数据库连接。不同的驱动(MySQL,Oracle等)都有对应的工厂来创建连接
github笔记