工厂模式

工厂模式是一种创建性模式。

它是最常用的一种设计模式,在Java系统中随时可见。(在DOM解析XML时就用到了) 。
它定义了一个创建对象的接口,让子类来决定具体实例化那一个类。
当一个类无法预料要创建那种类的对象时;或者一个类需要子类来指定创建的对象时, 我们就需要用到工厂模式。
简单来说,工厂模式可以根据不同的条件产生不同的实例。当然这些不同的实例都是属于相同类型的。
工厂模式把创建这些实例的具体过程封装起来。简化了实例化的操作,也改善了程序的扩展性和可延伸性。

上代码:

一、静态(简单)工厂模式:

比如说要吃面条,就要抽出一个面条的基类。让面馆作为一个工厂来决定做什么样的面条。
产品的抽象类:

public abstract class Inoodles {
    /*
     * 面条基类
     * 描述每种面条啥样的
     */
    public abstract void desc();
}

兰州拉面:

public class LzNooldles  extends Inoodles{
    /*
     * 兰州拉面
     */
    @Override
    public void desc() {
        System.out.println("兰州拉面");
    }

}

泡面:

public class PaoNoodles extends Inoodles {

    @Override
    public void desc() {
        System.out.println("加班必备的泡面");
    }

}

油泼面:

public class YouPoNooldes extends Inoodles {

    @Override
    public void desc() {
        System.out.println("陕西油泼面");
    }

}

面馆工厂类:

ublic class SimpleNooldlesFactory {
    /*
     * 面工厂
     */
    /*
     * 工场是一个具体的类,而不是接口抽象类。有一个重要的创建对象create()的方法。
     * create()方法是静态的。所以也称为静态工厂
     * 缺点:
     * 扩展性差。
     * 不同产品需要不同的额外参数时,特别麻烦。
     */
    public static final int TYPE_LZ=1;
    public static final int TYPE_PM=2;
    public static final int TYPE_YP=3;
    public static Inoodles createNoodles(int type){
        switch (type) {
        case TYPE_LZ:
            return new LzNooldles();
        case TYPE_PM:
            return new PaoNoodles();
        case TYPE_YP:
        default:
            return new YouPoNooldes();
        }
    }

}

测试:

    public static void main(String[] args) {
        Inoodles noodes=SimpleNooldlesFactory.createNoodles(SimpleNooldlesFactory.TYPE_PM);
        noodes.desc();
    }

输出:

加班必备的泡面

特点:

抽象工厂作为具体的类,而不是接口或者抽象类。
有一个重要的create()方法,利用if或者 switch创建产品并返回。
create()方法通常是静态的,所以也称之为静态工厂。

缺点

扩展性差(我想增加一种面条,除了新增一个面条产品类,还需要修改工厂类方法)
不同的产品需要不同额外参数的时候 不支持。

二:反射(简单)工厂模式:

利用反射Class.forName(clz.getName().newInstance())实现的简单工厂

ublic class StaticNoodlesFactory {
    /*
     * 利用反射Class。forName(clz.getName().newInstance())实现的简单工厂
     */
    @SuppressWarnings("unchecked")
    public static <T extends Inoodles> T createNoodles(Class<T>clz){
        T result=null;
        try {
            result=(T) Class.forName(clz.getName()).newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return result;
    }
}

测试类:

public class Test {
    public static void main(String[] args) {
        Inoodles lz=StaticNoodlesFactory.createNoodles(PaoNoodles.class);
        lz.desc();
    }
}

输出结果:

加班必备的泡面

特点

它也是一个具体的类,非接口抽象类。但它的create()方法,是利用反射机制生成对象返回,好处是增加一种产品时,不需要修改create()的代码。

缺点
这种写法粗看牛逼,细想之下,不谈reflection的效率还有以下问题:

Class.forName(clz.getName()).newInstance()调用的是无参构造函数生成对象,
它和new Object()是一样的性质,而工厂方法应该用于复杂对象的初始化 ,当需要调用有参的构造函数时便无能为力了,这样像为了工厂而工厂。
不同的产品需要不同额外参数的时候 不支持。

三:多工厂模式(常用)

使用前两种实现的工厂,都有一个缺点:不同的产品需要不同额外参数的时候 不支持。

而且如果使用时传递的type、Class出错,将不能得到正确的对象,容错率不高。

而多方法的工厂模式为不同产品,提供不同的生产方法,使用时 需要哪种产品就调用该种产品的方法,使用方便、容错率高。

public class MulWayNoodlesFactory {
    /*
     * 生产泡面
     */
    public static Inoodles createPao(){
        return new PaoNoodles();
    }
    /*
     * 生产兰州拉面
     */
    public static Inoodles createLz(){
        return new LzNooldles();
    }
    /*
     * 生产油泼面
     */
    public static Inoodles createYou(){
        return new YouPoNooldes();
    }
}
public class Test {
    public static void main(String[] args) {
        Inoodles in=MulWayNoodlesFactory.createPao();
        in.desc();
    }
}
加班必备的泡面

这种模式优点较大,增加一个新面条,只要去增加一个static方法即可,也不修改原方法逻辑。

四:普通工厂

public abstract class NoodlesFactory {
    public abstract Inoodles create();
}
public class LzNooldlese  extends NoodlesFactory{
    /*
     * 兰州拉面
     */

    @Override
    public Inoodles create() {
        return new LzNooldles();
    }


}
public class PaoNoodls extends NoodlesFactory {

    @Override
    public Inoodles create() {
        return new PaoNoodles();
    }

}
public class YouPoNoolds extends NoodlesFactory {


    @Override
    public Inoodles create() {
        return new YouPoNooldes();
    }

}
public class Test {
    public static void main(String[] args) {
        NoodlesFactory fac=new PaoNoodls();
        Inoodles sd=fac.create();
        sd.desc();

    }
}
加班必备的泡面

普通工厂就是把简单工厂中具体的工厂类,划分成两层:抽象工厂层+具体的工厂子类层。(一般->特殊)

普通工厂与简单工厂模式的区别:

可以看出,普通工厂模式特点:不仅仅做出来的产品要抽象, 工厂也应该需要抽象。

工厂方法使一个产品类的实例化延迟到其具体工厂子类.

工厂方法的好处就是更拥抱变化。当需求变化,只需要增删相应的类,不需要修改已有的类。

而简单工厂需要修改工厂类的create()方法,多方法静态工厂模式需要增加一个静态方法。

缺点:

引入抽象工厂层后,每次新增一个具体产品类,也要同时新增一个具体工厂类。

五:抽象工厂

以上介绍的工厂都是单产品系的。抽象工厂是多产品系 (貌似也有产品家族的说法)。

举个例子来说,每个店(工厂)不仅仅卖面条,还提供饮料卖。
提供饮料卖,饮料是产品,先抽象一个产品类,饮料:

public abstract  class Drinks {
    /*
     * 描述每种饮料多少钱
     */
    public abstract void prices();
}
public class Cola extends Drinks {

    @Override
    public void prices() {
        System.out.println("可乐3.5");
    }

}
public class Water extends Drinks {

    @Override
    public void prices() {
        System.out.println("水不要钱");
    }

}
public abstract class FoodFactory {
    /*
     * 生产面条
     */
    public abstract Inoodles createNoodels();
    /*
     * 生产饮料
     */
    public abstract Drinks createDrinks();
}
public class LzFoodFactory extends FoodFactory {

    @Override
    public Inoodles createNoodels() {
        return new LzNooldles();
    }

    @Override
    public Drinks createDrinks() {
        return new Water();
    }

}
public class KFC extends FoodFactory {

    @Override
    public Inoodles createNoodels() {
        return new PaoNoodles();
    }

    @Override
    public Drinks createDrinks() {
        return new Cola();
    }

}
public class Test {
    public static void main(String[] args) {
        FoodFactory fac=new KFC();
        fac.createDrinks().prices();
        fac.createNoodels().desc();
        fac=new LzFoodFactory();
        fac.createDrinks().prices();
        fac.createNoodels().desc();
    }
}
可乐3.5
加班必备的泡面
水不要钱
兰州拉面

小结:

将工厂也抽象了,在使用时,工厂和产品都是面向接口编程,OO(面向对象)的不得了。

缺点

但是将工厂也抽象后,有个显著问题,就是类爆炸了。而且每次拓展新产品种类,例如不仅卖吃卖喝,我还想卖睡,提供床位服务,这需要修改抽象工厂类,因此所有的具体工厂子类,都被牵连,需要同步被修改。

一句话总结工厂模式:方便创建 同种产品类型的 复杂参数 对象

工厂模式重点就是适用于 构建同产品类型(同一个接口、基类)的不同对象时,这些对象new很复杂,需要很多的参数,而这些参数中大部分都是固定的,so,懒惰的程序员便用工厂模式封装之。
如果构建某个对象很复杂,需要很多参数,但这些参数大部分都是“不固定”的,应该使用Builder模式。

为了适应程序的扩展性,拥抱变化,便衍生出了 普通工厂、抽象工厂等模式。

更多模式详见:
http://blog.csdn.net/zhangerqing/article/details/8194653
http://blog.csdn.net/column/details/code-design.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值