前言
本篇我们了解一下简单工厂模式,它是设计模式的雏形,是学习设计模式的开端,我会结合案例说明它的设计思路。
一、简单工厂模式定义
简单工厂模式并不是GoF23个设计模式中的一员,但是一般将它作为学习设计模式的起点。简单工厂模式又称为静态方法模式(Static Factory Method Pattern),属于类创建型模式。在简单工厂模式中,可以根据参数的不同返回不同的类的实例。简单工厂模式专门定义一个类来负责创建其他类的实例,这个类称为工厂类,被创建的实例通常都具有共同的父类。简单工厂模式的结构如下图:
在模式结构图中,Factory表示工厂类,它是整个模式的核心,负责实现创建所有实例的内部逻辑。工厂类可以被外部直接调用,创建所需的产品对象。工厂类中有一个负责生产对象的静态工厂方法,系统可以根据工厂方法所传入的参数,动态决定应该创建出哪一个产品类的实例。工厂方法是静态的,而且必须有返回类型,其返回类型为抽象产品类型,即Product类型;Product表示抽象产品角色,它是简单工厂模式所创建的所有对象的父类,负责定义所有实例所共有的公共接口;ConcreteProduct表示具体产品角色,它是简单工厂模式的创建目标,所有创建的对象都是充当这个角色的某个具体类的实例。一个系统中一般存在多个ConcreteProduct类,每种具体产品对应一个Concrete类。
二、举个例子
我们设计一个Coffee(咖啡类),它是一个抽象类,比如现在有两种具体咖啡,分别是AmericanCoffee(美式咖啡)和LatteeCoffee(拿铁咖啡),因此我们需要一个具体工厂去创建具体咖啡产品,我们再定义一个生产咖啡的工厂SimpleCoffeeFactory,它们的模式结构图如下:
AmericanCoffee和LatteeCoffee需要继承Coffee这个抽象产品,同时都要实现Coffee中的抽象方法,比如获取咖啡名称,添加牛奶,加糖等方法,而SimpleCoffeeFactory是生产咖啡的工厂,需要提供一个静态的创建咖啡的方法,同时这个方法的返回值类型必须是Coffee抽象类,这就体现了多态的特性,即父类引用可以指向子类对象。
相关代码如下:
抽象咖啡类,其实也可以是接口,我定义的是抽象类:
abstract public class Coffee {
abstract protected void getName();
abstract protected void addMilk();
abstract protected void addSugar();
}
美式咖啡(具体产品):
public class AmericanCoffee extends Coffee{
@Override
protected void getName() {
System.out.println("American Coffee...");
}
@Override
protected void addMilk() {
System.out.println("add American coffee milk...");
}
@Override
protected void addSugar() {
System.out.println("add American coffee sugar...");
}
}
拿铁咖啡(具体产品):
public class LatteCoffee extends Coffee{
@Override
protected void getName() {
System.out.println("Latte Coffee...");
}
@Override
protected void addMilk() {
System.out.println("add Latte Coffee milk...");
}
@Override
protected void addSugar() {
System.out.println("add Latte Coffee sugar...");
}
}
咖啡工厂类:
public class SimpleCoffeeFactory {
public static Coffee createFactory(String type){
Coffee coffee = null;
if ("AmericanCoffee".equals(type)){
coffee = new AmericanCoffee();
} else if ("LatteeCoffee".equals(type)) {
coffee = new LatteCoffee();
}
return coffee;
}
}
在咖啡工厂类中定义了一个创建咖啡的静态方法,入参是咖啡的类型,根据类型判断返回具体咖啡对象。
在外部可以创建一个咖啡店类,调用工厂提供的静态方法去创建具体的咖啡:
public class CoffeeStory {
public static void main(String[] args) {
orderCoffee("AmericanCoffee");
}
public static Coffee orderCoffee(String name){
SimpleCoffeeFactory simpleCoffeeFactory = new SimpleCoffeeFactory();
Coffee coffee = simpleCoffeeFactory.createFactory(name);
coffee.getName();
coffee.addMilk();
coffee.addSugar();
return coffee;
}
}
三、简单工厂模式的缺点
在简单工厂模式中,工厂类包含必要的判断逻辑,决定在什么时候创建哪一个产品类的实例,客户端可以直接免除直接创建产品对象的责任,而仅仅“消费”产品,简单工厂模式通过这种方式实现了对责任的划分。但是由于工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响;同时系统扩展较为困难,一旦添加新产品就不得不修改工厂逻辑,违反了开闭原则。比如上面的案例,如果我们再增加一种意大利咖啡,那么在创建具体产品类的同时,静态工厂方法的代码逻辑需要改动。因此,简单工厂模式是存在很多问题的,通常并不用于实际开发中。
总结
本篇我们结合实际案例说明了简单工厂模式的设计原理,和它包含的角色,下面我们继续看另一种设计更合理的工厂方法模式。