JAVA设计模式:工厂模式(面试必备)

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

1.首先建立一个产品的抽象类
需要生产什么产品就需要建立一个相应产品的抽象

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

2.再建立几种具体的产品类:
例如:兰州拉面,泡面,干吃面

public class LzNoodles extends INoodles {
    @Override
    public void desc() {
        System.out.println("兰州拉面");
    }
}
public class PaoNoodles extends INoodles {
    @Override
    public void desc() {
        System.out.println("泡面");
    }
}
public class GankouNoodles extends INoodles {
    @Override
    public void desc() {
        System.out.println("干吃面");
    }
}

3.在建立完这些产品后就可以建立(造面的)工厂了:

工厂里面包含了我们可以生产的产品(面)
public class SimpleNoodlesFactory {
    public static final int TYPE_LZ = 1;//兰州拉面
    public static final int TYPE_PM = 2;//泡面
    public static final int TYPE_GK = 3;//干吃面

    public static INoodles createNoodles(int type) {
        switch (type) {
            case TYPE_LZ:
                return new LzNoodles();
            case TYPE_PM:
                return new PaoNoodles();
            case TYPE_GK:
            default:
                return new GankouNoodles();
        }
    }
}

4.开始根据客人的要求生产产品

如下代码是生产干吃面的过程。

INoodles noodles = SimpleNoodlesFactory.createNoodles(SimpleNoodlesFactory.TYPE_GK);
 noodles.desc();

该设计模式只可以生产工厂能生产的产品,如需要增加产品,需要在工厂类中增加相应的静态变量。

特点

1 它是一个具体的类,非接口 抽象类。有一个重要的create()方法,利用if或者 switch创建产品并返回。

2 create()方法通常是静态的,所以也称之为静态工厂。

缺点

1 扩展性差(我想增加一种面条,除了新增一个面条产品类,还需要修改工厂类方法)

2 不同的产品需要不同额外参数的时候 不支持。

二、另一种简单工厂(反射):

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

public class StaticNoodlesFactory {
    /**
     * 传入Class实例化面条产品类
     *
     * @param clz
     * @param <T>
     * @return
     */
    public static <T extends INoodles> T createNoodles(Class<T> clz) {
        T result = null;
        try {
            result = (T) Class.forName(clz.getName()).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
}
特点

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

三、多方法工厂(常用)

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

工厂如下:

public class MulWayNoodlesFactory {

    /**
     * 模仿Executors 类
     * 生产泡面
     *
     * @return
     */
    public static INoodles createPm() {
        return new PaoNoodles();
    }

    /**
     * 模仿Executors 类
     * 生产兰州拉面
     *
     * @return
     */
    public static INoodles createLz() {
        return new LzNoodles();
    }

    /**
     * 模仿Executors 类
     * 生产干扣面
     *
     * @return
     */
    public static INoodles createGk() {
        return new GankouNoodles();
    }
}

这种我比较青睐,增加一个新面条,只要去增加一个static方法即可,也不修改原方法逻辑

四 普通工厂

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

面条工厂(抽象工厂类),作用就是生产面条:

public abstract class NoodlesFactory {
    public abstract INoodles create();
}

兰州拉面工厂(具体工厂子类)

public class LzFactory extends NoodlesFactory {
    @Override
    public INoodles create() {
        return new LzNoodles();
    }
}

泡面工厂 (具体工厂子类):

public class PaoFactory extends NoodlesFactory {
    @Override
    public INoodles create() {
        return new PaoNoodles();
    }
}

干吃面工厂 (具体工厂子类):

public class GankouFactory extends NoodlesFactory {
    @Override
    public INoodles create() {
        return new GankouNoodles();
    }
}

使用时:

     /**
         * 普通工厂方法:
         */
        System.out.println("===========================普通工厂方法==============================" +
                "\n 这种要多写一个类,不过更面向对象");
        NoodlesFactory factory1 = new GankouFactory();
        INoodles gk3 = factory1.create();
        gk3.desc();
普通工厂与简单工厂模式的区别:

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

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

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

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

六 抽象工厂

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

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

public abstract class IDrinks {
    /**
     * 描述每种饮料的价格
     */
    public abstract void prices();
}

然后实现两个具体产品类:
可乐:

public class ColaDrinks extends IDrinks {
    @Override
    public void prices() {
        System.out.println("可乐三块五");
    }
}

白开水

public class WaterDrinks extends IDrinks {
    @Override
    public void prices() {
        System.out.println("和我一样的穷鬼都喝水,不要钱~!");
    }
}

抽象饭店,无外乎吃喝(抽象工厂类):

public abstract class AbstractFoodFactory {
    /**
     * 生产面条
     *
     * @return
     */
    public abstract INoodles createNoodles();

    /**
     * 生产饮料
     */
    public abstract IDrinks createDrinks();
}

兰州大酒店(具体工厂类):

public class LzlmFoodFactory extends AbstractFoodFactory {
    @Override
    public INoodles createNoodles() {
        return new LzNoodles();//卖兰州拉面
    }

    @Override
    public IDrinks createDrinks() {
        return new WaterDrinks();//卖水
    }
}

KFC(具体工厂类):

public class KFCFoodFactory extends AbstractFoodFactory {
    @Override
    public INoodles createNoodles() {
        return new PaoNoodles();//KFC居然卖泡面
    }

    @Override
    public IDrinks createDrinks() {
        return new ColaDrinks();//卖可乐
    }
}

使用:

        /**
         * 抽象工厂方法:
         */
        System.out.println("==============================抽象方法==============================" )
                
        AbstractFoodFactory abstractFoodFactory1 = new KFCFoodFactory();
        abstractFoodFactory1.createDrinks().prices();
        abstractFoodFactory1.createNoodles().desc();

        abstractFoodFactory1= new LzlmFoodFactory();
        abstractFoodFactory1.createDrinks().prices();
        abstractFoodFactory1.createNoodles().desc();

输出:

==============================抽象方法==============================
可乐三块五
泡面
和我一样的穷鬼都喝水,不要钱~!
兰州拉面

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

学习参考

https://blog.csdn.net/zxt0601/article/details/52798423

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值