用工厂方法模式吃上不同品种的水果
定义
工厂方法模式(Factory Method Pattern)定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个,工厂方法模式让类把实例化推迟到子类。
适用场景
我们创建实例的一般方式是用new,举个最简单的例子
Fruit apple=new Apple();
apple的类型是接口或者抽象类,符合“针对接口编程,而不是针对实现编程”的设计原则,但new后面依然是具体实现类Apple,这不利于代码的扩展,比如我们分情况需要创建Apple Orange Banana,代码可能写成
Fruit fruit;
if (type=="apple"){
fruit=new Apple();
}
else if (type=="orange"){
fruit=new Orange();
}
else{
fruit=new Banana();
}
我们有多个场景需要创建三种水果之一,那么上述代码就会在每个场景下重复,如果我们把上述代码封装成方法,并放进一个类中,那我们就无意中使用了一个设计模式–简单工厂模式(Simple Factory Pattern),这个类就是工厂类,下面是可能的代码
public class FruitFactory {
Fruit getFruit(String type){
Fruit fruit;
if (type=="apple"){
fruit=new Apple();
}
else if (type=="orange"){
fruit=new Orange();
}
else{
fruit=new Banana();
}
return fruit;
}
}
需要创建三种水果之一的场景只需要创建FruitFactory并调用getFruit就可以得到想要的水果。
但简单工厂模式存在一些问题,多个产品通过一个工厂生产出来,如果工厂方法实现有误,会导致需要种类产品无法生产,如果我要对产品的种类进行增删查改,则只能进入源代码修改工厂类,这说明简单工厂没有很好地体现“类应该对扩展开放,对修改关闭”的设计原则。
工厂方法模式可以解决简单工厂模式上述的问题。工厂方法模式定义了工厂接口和产品接口,随后让每一个工厂子类或实现了工厂接口的类负责一个具体产品的生产。简单工厂模式是一个工厂生产多种产品,工厂方法模式是一个子工厂生产一种产品。需要增加新产品时增加新产品与新工厂的类即可,无需修改已有的类,删除产品时也只需要删除对应产品与工厂的类即可。
例子
用水果做例子,水果是产品,有Apple、Orange、Banana三种,对应实现三种水果生产工厂,下面是UML类图
每一个工厂都会在getFruit方法中返回对应的水果,所以图中最下面三条连线表示水果工厂与水果的关联关系
下面是代码
Fruit.java
package priv.mxz.design_pattern.factory_method_pattern;
interface Fruit {
void showName();
}
class Apple implements Fruit{
@Override
public void showName() {
System.out.println("Apple");
}
}
class Orange implements Fruit{
@Override
public void showName() {
System.out.println("Orange");
}
}
class Banana implements Fruit{
@Override
public void showName() {
System.out.println("Banana");
}
}
FruitFactory.java
package priv.mxz.design_pattern.factory_method_pattern;
interface FruitFactory {
Fruit getFruit();
}
class AppleFactory implements FruitFactory{
@Override
public Fruit getFruit() {
return new Apple();
}
}
class OrangeFactory implements FruitFactory{
@Override
public Fruit getFruit() {
return new Orange();
}
}
class BananaFactory implements FruitFactory{
@Override
public Fruit getFruit() {
return new Banana();
}
}
FactoryMethodPattern.java
package priv.mxz.design_pattern.factory_method_pattern;
public class FactoryMethodPattern {
public static void main(String[] args) {
FruitFactory apple_factory=new AppleFactory();
FruitFactory orange_factory=new OrangeFactory();
FruitFactory banana_factory=new BananaFactory();
Fruit fruit=apple_factory.getFruit();
fruit.showName();
fruit=orange_factory.getFruit();
fruit.showName();
fruit=banana_factory.getFruit();
fruit.showName();
}
}
FactoryMethodPattern中有程序入口,做的事情只是实例化每个工厂,并调用getFruit拿到水果,并打印水果名字
输出
Apple
Orange
Banana
优缺点
相比简单工厂模式,工厂方法模式更好地体现了“类应该对扩展开放,对修改关闭”的设计原则,产品的增删查改不会影响其他已有的代码,这是主要的优点
但我们也可以看到,工厂方法模式的类的数目比简单工厂模式的是要多的,一个产品要有一个对应的类,如果产品过多会导致类数目城北增加。
总结
工厂方法模式是一种创建型设计模式,每一个工厂负责一件产品的生产,用户不需要知道具体的产品信息,只需要知道对应的工厂即可以生产产品。工厂方法模式比简单工厂模式更符合”开闭原则“。但类的数目比简单工厂模式要多。