前言
工厂方法模式是应用比较广泛的一种设计模式,它相对于简单工厂模式进行了一些优化,如果再增加一个具体产品不用修改代码,也不会违反开闭原则。
一、工厂方法模式的定义
工厂方法模式也称为工厂模式,又称为虚拟构造器(Virtual Constructor)模式或多态模式,属于类创建型模式。在工厂方法模式中,父类负责定义创建对象的公共接口,而子类则负责生成具体的对象,这样做的目的是将类的实例化延迟到子类中完成,即由子类来决定究竟应该实例化哪一个类,工厂方法模式结构图如下图所示:
在模式结构图中,Product表示抽象产品,它定义了产品的接口;ConcreteProduct表示具体产品,它实现抽象产品的接口;Factory表示抽象工厂,它声明了工厂方法(FactoryMethod),返回一个产品;ConcreteFactory表示具体工厂,它实现工厂方法,由客户端调用,返回一个产品实例。在工厂方法模式中,工厂方法模式的核心是抽象工厂类Factory,各种具体工厂类继承抽象工厂类并实现在抽象工厂类中定义的工厂方法,从而使得客户端只关心抽象产品和抽象工厂,完全不用理会返回的是哪一种具体产品,也不用关系它是如何被具体工厂创建的。
二、举个例子
定义一个Coffee类,它是抽象产品,还有一个CoffeeFactory它是抽像工厂,还有一个具体产品AmericanCoffee继承Coffee类,同时要有一个AmericanCoffeeFactory它要继承CoffeeFactory,另外还有一个LatteeCoffee它也是具体产品需要继承Coffee,同时有一个具体工厂生产这种产品就是LatteeCoffeeFactory。它的模式结构图如下:
Coffee抽象类:
abstract public class Coffee {
abstract protected void getName();
abstract protected void addMilk();
abstract protected void addSugar();
}
AmericanCoffee:
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...");
}
}
LatteeCoffee:
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...");
}
}
AmericanCoffeeFactory:
public class AmericanCoffeeFactory extends CoffeeFactory {
@Override
protected Coffee createCoffee() {
return new AmericanCoffee();
}
}
LatteeCoffeeFactory:
public class LatteeCoffeeFactory extends CoffeeFactory {
@Override
protected Coffee createCoffee() {
return new LatteCoffee();
}
}
客户端:
public class CoffeeStory {
private static CoffeeFactory coffeeFactory;
public static void main(String[] args) {
CoffeeStory coffeeStory = new CoffeeStory(new AmericanCoffeeFactory());
coffeeStory.orderCoffee();
}
public CoffeeStory(CoffeeFactory coffeeFactory){
this.coffeeFactory = coffeeFactory;
}
public Coffee orderCoffee(){
Coffee coffee = coffeeFactory.createCoffee();
coffee.addMilk();
coffee.getName();
coffee.addSugar();
return coffee;
}
}
在客户端我们定义一个静态抽象工厂的引用类型,同时重载构造方法,形式参数就是抽象工厂类型,当客户端调用的时候,可以传入具体工厂类型,那么抽象工厂引用就会指向具体子类工厂,这也体现了多态的思想。
三、工厂方法模式的缺点
在系统中加入新产品时吗,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他具体工厂和具体产品,而只要添加一个具体工厂和具体产品即可,这样,系统的可扩展性也就变得非常好,符合开闭原则。但是在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,难免会增加系统类的个数,增加系统的开销。
总结
本篇就是对工厂方法模式进行的一个设计原理分析。