工厂方法模式最常用的设计模式之一。它在创建实例对象中的作用堪比我们经常用到的new机制。这种设计模式将对象的创建规则放在父类中,而所有实现细节都留给子类自由发挥,具有强大的扩展能力。在这里将以经营一家奶茶店来理解工厂方法模式的优点。
首先,创建一家奶茶店,经营多种奶茶:
public class MilkTeaSeller{
public void OrderMilkTea(int style){
if(style==1)
return getCommonMilkTea();
else if(style==2)
return getAppleStyleMilkTea();
}
Private CommonMilkTea getCommonMilkTea(){
CommonMilkTea common= CommonMilkTea(); //下了“要一杯普通买茶的命令”
/*
* 奶茶的制作过程简化为:prepare,addwater,mix capsulate四个步骤,而根据奶茶的* 种类不同,步骤间也有些差异
*/
common.preapre();
common.addWater();
common.mix();
common.encapsulate();
}
}
上面几句代码简单地模拟了下订单以及生产奶茶的过程。根据客户要求style生成不同类型的奶茶。上面这种方法存在不少的问题。虽然思路上很清晰,但是,假如奶茶店卖的奶茶种类有几十种,那这个类的代码行数将是巨大的。并且,在这么长的代码量后面,生产奶茶的四大步骤重复了一遍又一遍。假如哪天发现卖奶茶不赚钱,想卖面包。很多人想把上面代码改改,用到面包店上,却发现还不如重新编写代码来的简单。于是,我们想到了工厂方法模式,在父类中规定了创建对象的规则,而实现细节由子类自由发挥。因为,种类繁多的奶茶之间都有共同点(生产步骤一样)把这些共同点进行抽象形成父类,而各种奶茶的具体制作细节放在各自的类中完成。先来看看工厂方法模式的结构:1 抽象工厂:和抽象产品组成了整个模式的框架,它运用了模板方法模式,定义了生产产品的基本规则(基本框架),而具体细节对它来说一无所知。它将返回了一个抽象产品。 2 抽象产品:定义了这个模式所产生的对象具备的API,具体细节由子类实现。3 具体工厂:实现抽象工厂中的抽象方法,返回具体产品。4 具体产品:不同具体产品的实现细节。/* AbstractFactory .java */ package FactoryMethodPattern.FrameWork; import FactoryMethodPattern.FrameWork.AbstractProduct; /* * 采用工厂方法模式模拟奶茶店的运营 * 抽象工厂类:AbstractFactory * 抽象产品类:AbstractProduct * 具体工厂类:MilkTeaFactory * 具体产品类:MilkTeaCommon */ public abstract class AbstractFactory{ public AbstractProduct OrderProduct(int style){ AbstractProduct p=createProduct(style); p.prepare(); p.addWater(); p.Mix(); p.encapsulation(); return p; } /* * 抽象方法,由子类实现,用于创建产品 */ public abstract AbstractProduct createProduct(int style); } /* AbstractProduct.java */ package FactoryMethodPattern.FrameWork; public abstract class AbstractProduct{ public abstract void prepare(); public abstract void addWater(); public abstract void Mix(); public abstract void encapsulation(); } /* MilkTeaFactory.java */ package FactoryMethodPattern.Concrete; import FactoryMethodPattern.FrameWork.AbstractFactory; import FactoryMethodPattern.FrameWork.AbstractProduct; import java.lang.RuntimeException;; public class MilkTeaFactory extends AbstractFactory{ public MilkTeaFactory(){ System.err.println("create a new milkTeaFactory"); } public AbstractProduct createProduct(int style) throws RuntimeException{ if(style==1) return new MilkTeaCommon(); else throw new RuntimeException("No such exception"); } } /* MilkTeaCommon.java */ package FactoryMethodPattern.Concrete; import FactoryMethodPattern.FrameWork.AbstractProduct; public class MilkTeaCommon extends AbstractProduct{ public MilkTeaCommon(){ System.err.println("Create a cup of common MilkTea"); } public void prepare(){ System.err.println("prepare the required material"); } public void addWater(){ System.err.println("add some water"); } public void Mix(){ System.err.println("mix about 10 seconds"); } public void encapsulation(){ System.err.println("encapsulate in common style"); } } 当需要增加奶茶种类的时候,很简单,只需要做简单的修改。如增加:苹果味的奶茶。 /* 增加具体产品类 */ /* MilkTeaWithApple */ package FactoryMethodPattern.Concrete; import FactoryMethodPattern.FrameWork.AbstractProduct; public class MilkTeaWithApple extends AbstractProduct{ public MilkTeaWithApple(){ System.err.println("Create a cup of APPLE style MilkTea"); } public void prepare(){ System.err.println("prepare the required material for the apple style milkTea"); } public void addWater(){ System.err.println("add some water for the apple style milkTea"); } public void Mix(){ System.err.println("mix about 10 seconds for the apple style milkTea"); } public void encapsulation(){ System.err.println("encapsulate for the apple style milkTea"); } } 修改具体工厂中的方法: public AbstractProduct createProduct(int style) throws RuntimeException{ if(style==1) return new MilkTeaCommon(); else if(style==2) return new MilkTeaWithApple(); else throw new RuntimeException("No such exception"); } 最后来看看我们的Main函数(Client) package FactoryMethodPattern; import FactoryMethodPattern.FrameWork.*; import FactoryMethodPattern.Concrete.*; public class Main{ /* * 整个调用过程相当简单,所涉及到的对象也很少。 */ public static void main(String[] args){ AbstractFactory af=new MilkTeaFactory(); af.OrderProduct(1); //order a cup of MilkTea in common style af.OrderProduct(2); // order a cup of MilkTea in apple style } }