在这篇博客中,将讲解工厂方法模式,需要再次强调一下凡是提到工厂模式都是用来产生对象用的,下面开始思考这么一个场景:
小张喜欢吃烤鱼,于是他走到他家附近的一家烤鱼店,跟服务员说,我要烤鲤鱼一份,然后找了个桌子,安心的坐下等待上菜,对于烤鱼店来说,他们接收到小张下的烤鲤鱼订单,首先准备一条鲤鱼,然后去清理,蒸熟,加上佐料烤,然后上桌,这么个过程,首先先编写一个鱼类及其部分子类,如下:
public interface Fish {
// 外观展示
public void display();
// 是否是淡水鱼
public boolean isFWF();
}
/*
* 鲤鱼
*/
class Carp implements Fish{
@Override
public void display() {
// TODO Auto-generated method stub
System.out.println("我是一条鲤鱼");
}
@Override
public boolean isFWF() {
// TODO Auto-generated method stub
return true;
}
}
/*
* 鲶鱼
*/
class CatFish implements Fish{
@Override
public void display() {
// TODO Auto-generated method stub
System.out.println("我是一条鲶鱼");
}
@Override
public boolean isFWF() {
// TODO Auto-generated method stub
return true;
}
}
/*
* 刀鱼
*/
class KnifeFish implements Fish{
@Override
public void display() {
// TODO Auto-generated method stub
System.out.println("我是一条刀鱼");
}
@Override
public boolean isFWF() {
// TODO Auto-generated method stub
return false;
}
}
下面在编写烤鱼店处理类,需要将该类声明为抽象类,并且在该类中提供一个抽象的工厂方法,代码如下:
/*
* 烤鱼店
*/
public abstract class GrillFishStore {
// 用户下订单的鱼
private Fish fish;
// 订单处理方法,其中过程包括准备一条鲤鱼,然后清理,蒸熟,加上佐料烤,最后返回成品的烤鱼
public Fish orderFish(String fishType) {
// 获取用户下订单的鱼
fish = createFish(fishType);
// 清理杂物
cleanFish(fish);
// 蒸熟
steam(fish);
// 加佐料烤
roastWithSeasoning(fish);
return fish;
}
// 清理
public void cleanFish(Fish fish){
}
// 蒸熟
public void steam(Fish fish){
}
// 佐料烤
public void roastWithSeasoning(Fish fish){
}
// 获取对应的鱼类
abstract Fish createFish(String fishType);
}
现在已经有了一个GrillFishStore作为超类,在每个地区有若干个各种品牌的烤鱼店,让每个品牌的烤鱼店都继承这个GrillFishStore,每个子类各自决定如何制造鱼类,子类如下:
/*
* 诸葛烤鱼,一个只对鲤鱼和刀鱼进行烧烤的烤鱼店
*/
public class ZhugeGrillFishStore extends GrillFishStore {
@Override
public Fish createFish(String fishType) {
if ("Carp".equals(fishType)) {
return new Carp();
} else if ("KnifeFish".equals(fishType)) {
return new KnifeFish();
} else
return null;
}
}
/*
* 茅庐烤鱼,一个只对鲤鱼和鲶鱼进行烧烤的烤鱼店
*/
public class MaoluGrillFishStore extends GrillFishStore {
@Override
public Fish createFish(String fishType) {
if ("Carp".equals(fishType)) {
return new Carp();
} else if ("CatFish".equals(fishType)) {
return new CatFish();
} else
return null;
}
}
这样一来,将原本有一个简单工厂类来负责实现所有具体类的实例化,现在通过对GrillFishStore做一些小转变,编程由一群子类来负责实例化;
工厂方法就是用来处理对象的创建,并将这样的行为封装在子类中。这样客户程序关于超类的代码就和子类对象创建代码解耦:
// abstract -> 工厂方法必须声明为抽象的,所以依赖子类来处理对象的创建
// Product -> 工厂方法必须返回一个产品,通常使用工厂方法的返回值
// factoryMethod -> 工厂方法将超类中的代码(如orderFish方法)和实际创建具体产品的代码分割开来
// type -> 工厂方法可能需要参数(也可能不需要),来指定所要的产品
abstract Product factoryMethod(String type);
工厂方法模式并不难理解,核心点在于超类用来声明工厂方法,且限制流程,在子类中去实现具体对象的创建过程,如果对比简单工厂的话,理解起来就会轻松很多!!当你没事多读读源码的话会发现有好多的源码都采用的是工厂方法模式!
所有工厂模式都用来封装对象的创建。工厂方法模式通过让子类决定该创建的对象是什么,来达到将对象创建的过程封装的目的,下面让我们来看看类图:
GrillFishStore类就是创建者类,它定义了一个抽象的工厂方法,让子类实现此方法制造产品,创建者通常会包含依赖于抽象产品的代码,而这些抽象产品由子类创造,创建者不需要指的知道在制造哪种具体产品,MaoluGrillFishStore和ZhugeGrillFishStore类是GrillFishStore类的子类,所以可以实现createFish方法创建自己的对象;
工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到了子类;工厂方法模式能够封装具体类型的实例化。在抽象的创建者类中,任何其它实现的方法,都可能使用到这个工厂方法所制造出来的产品,但只有子类真正实现这个工厂方法并创建产品。