1.什么是工厂模式?
继续援引百度百科定义:工厂模式是我们最常用的实例化对象模式了,是用工厂方法代替new操作的一种模式。著名的Jive论坛 ,就大量使用了工厂模式,工厂模式在Java程序系统可以说是随处可见。因为工厂模式就相当于创建实例对象的new,我们经常要根据类Class生成实例对象,如A a=new A() 工厂模式也是用来创建实例对象的,所以以后new时就要多个心眼,是否可以考虑使用工厂模式,虽然这样做,可能多做一些工作,但会给你系统带来更大的可扩展性和尽量少的修改量。
说简单点就是通过工厂来生产我们原来需要手动去new的对象,大名鼎鼎的spring中bean就用到了工厂.
2.为什么使用工厂模式?
其实上面百度百科定义中已经提到了,通过工厂模式可以增加系统的可扩展性,减少代码的修改量,可以让代码维护起来更容易.
3.如何实现?
工厂的实现有两种方式,一种是简单工厂,一种是抽象工厂,前者实现简单,后者更为灵活.
3.1简单工厂(简单工厂我就不写了,太简单了,这里直接实现工厂方法模式)
我以现实生活中一个例子来实现,帮助理解.我开了一家包子店,一开始规模比较小,我只卖包子,包子有猪肉包,有奶黄包,有豆腐包…
如果我没有一个生产包子的工厂,那顾客要啥包子我就去做啥包子,那么多种包子我不得累死啊…现在好了,有了工厂,顾客想要啥包子,工厂就给我去生产啥包子,再也不用我操心了,真好…
①创建一个接口,Stuffing()方法决定包子是啥馅的
public interface Baozi {
void Stuffing();//啥馅
}
②各种馅分别去实现这个接口
public class Meat implements Baozi {
@Override
public void Stuffing() {
System.out.println("鲜肉包...");
}
}
public class Tofu implements Baozi{
@Override
public void Stuffing() {
System.out.println("豆腐包...");
}
}
public class Cream implements Baozi {
@Override
public void Stuffing() {
System.out.println("奶黄包...");
}
}
③创建生产包子的工厂类
/**
*生产包子工厂
*/
public class Factory {
public static Baozi getBaozi(String BaoziType) {
switch (BaoziType) {
case "cream":
return new Cream();
case "meat":
return new Meat();
case "tofu":
return new Tofu();
default:
throw new RuntimeException("对不起,没有这种包子...");
}
}
}
④测试下卖包子
/**
* 模拟卖包子
*/
public class SellBaoziTest {
public static void main(String[] args) {
//顾客一:老板,我要个肉包
Factory.getBaozi("meat").Stuffing();
//顾客二:老板,我要个豆腐包
Factory.getBaozi("tofu").Stuffing();
//顾客三:老板,我要个奶黄包
Factory.getBaozi("cream").Stuffing();
//顾客四:老板,我要个大沙包
Factory.getBaozi("sb").Stuffing();
}
}
运行后结果如图:
tip:包子工厂中我使用了switch case,其中case的类型为String,jdk1.7以后才支持这种语法,如果你的jdk版本低于1.7,你可以用If语句去实现.
这种方式果然好啊,我只管卖包子,包子不用自己做,不累…很快我发家致富了,我不再满足于卖卖包子了,我想包子豆浆一起卖,还想再卖点饮料…那我的包子工厂只能造包子啊,顾客需要红枣味的豆浆,芝麻味的豆浆,枸杞味的豆浆…我都得自己去做吗?那不是又要累死我,于是抽象工厂出现了,有了抽象工厂,管你是要卖包子还是卖豆浆还是卖饮料或是卖其它的东西,我都能给你造,只要你有钱,我就能造!
3.2抽象工厂
抽象工厂其实是工厂的工厂,怎么理解呢?原来我们的工厂是决定生产什么豆浆或者什么包子,但现在的工厂是用来决定生产的是包子工厂还是豆浆工厂,说起来有点绕,还是直接上代码吧:
①新增豆浆生产工厂,与上面的包子工厂中的步骤一样,只不过这里是生产豆浆,为了节省空间我这里一次性贴出来:
public interface Doujiang {
void flavor();//啥味
}
public class Jujube implements Doujiang {
@Override
public void flavor() {
System.out.println("红枣豆浆...");
}
}
public class Sesame implements Doujiang {
@Override
public void flavor() {
System.out.println("芝麻豆浆...");
}
}
public class DoujiangFactory {
public static Doujiang getDoujiang(String DoujiangType) {
switch (DoujiangType) {
case "jujube":
return new Jujube();
case "sesame":
return new Sesame();
default:
throw new RuntimeException("对不起,没有这种豆浆...");
}
}
}
②:创建一个接口,type()方法决定工厂类型是包子工厂还是豆浆工厂
public interface Type {
Object type();//啥工厂
}
③:各种工厂分别去实现这个接口
public class BaoziType implements Type{
@Override
public Object type() {
return new BaoziFactory();
}
}
public class DoujiangType implements Type {
@Override
public Object type() {
return new DoujiangFactory();
}
}
④:创建生产各种工厂的抽象工厂类
public class AbstractFactory {
public static Type getType(String ProdType){
switch (ProdType) {
case "doujiang" : return new DoujiangType();
case "baozi" : return new BaoziType();
default : throw new RuntimeException("不存在这种类型的工厂");
}
}
}
⑤:新店升级开业了,测试一下卖包子又卖豆浆:
/**
* 模拟卖包子和豆浆
*/
public class TestAbstractFactory {
public static void main(String[] args) {
//顾客一:我要一个肉包,一杯芝麻豆浆
Object obj1 = AbstractFactory.getType("baozi").type();
if (obj1.getClass().getName().equals(BaoziFactory.class.getName())){
BaoziFactory.getBaozi("meat").Stuffing();
}
Object obj2 = AbstractFactory.getType("doujiang").type();
if (obj2.getClass().getName().equals(DoujiangFactory.class.getName())){
DoujiangFactory.getDoujiang("sesame").flavor();
}
//顾客二:我要一个豆腐包,一杯红枣豆浆
Object obj3 = AbstractFactory.getType("baozi").type();
if (obj3.getClass().getName().equals(BaoziFactory.class.getName())){
BaoziFactory.getBaozi("tofu").Stuffing();
}
Object obj4 = AbstractFactory.getType("doujiang").type();
if (obj4.getClass().getName().equals(DoujiangFactory.class.getName())){
DoujiangFactory.getDoujiang("jujube").flavor();
}
//顾客三:我要一个登山包,一杯柠檬汁
Object obj5 = AbstractFactory.getType("dengshanbao").type();
if (obj5.getClass().getName().equals(BaoziFactory.class.getName())){
BaoziFactory.getBaozi("sb").Stuffing();
}
Object obj6 = AbstractFactory.getType("yinliao").type();
if (obj6.getClass().getName().equals(DoujiangFactory.class.getName())){
DoujiangFactory.getDoujiang("sb").flavor();
}
}
}
来看下结果:
符合预期,如果以后要卖饮料或者其它商品,只需要继续造工厂即可,现在再回过头来理解抽象工厂就是工厂的工厂这句话就比较容易理解了,这种抽象工厂模式在spring源码中有很多体现.