设计模式-工厂模式

    工厂模式在开发中应该算是使用的比较多了,比如做图形处理的时候,每种不同的图形需要不同的图形类去处理,这些图形类就可以继承一个图形的抽象类,实现handle方法;然后根据图形的类型,创造不同的图形类去处理不同的图形逻辑;

    工厂模式属于“创建型”的设计模式,使用工厂来代替了new操作的模式;在实际使用的时候,又有几种不同的类型;下面来简单了解下:

1>简单静态工厂

举个例子,有个面条的抽象类,有一个描述的方法,如下

package com.example.springbootDemo.service.factory;

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

然后我们分别定义三种具体的面条,分别如下

package com.example.springbootDemo.service.factory;

public class LzNoodles extends INoodles{
    @Override
    public void desc() {
        System.out.println("兰州拉面 上海的好贵 家里才5 6块钱一碗");
    }
}
public class PaoNoodles extends INoodles {
    @Override
    public void desc() {
        System.out.println("泡面好吃 可不要贪杯");
    }
}
public class GankouNoodles extends INoodles {
    @Override
    public void desc() {
        System.out.println("还是家里的干扣面好吃 6块一碗");
    }
}

之后我们定义一个工厂来生产面条

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();
        }
    }
}

调用的方法

public static void main(String[] args) {
        INoodles noodles = SimpleNoodlesFactory.createNoodles(SimpleNoodlesFactory.TYPE_LZ);
        noodles.desc();
    }

这种方式就是简单静态工厂模式;其实跟new一个对象的区别就是延迟了对象的创建过程,或者说封装了对象的创建,把这个创建的过程放在一个单独的类里面根据类型创造出来,这个类就是工厂。

特点:1.该工厂是一个具体的类,有一个create的方法来生成对应的不同的产品(面条),根据类型(if/switch)来判断是哪种产品,new不同的产品类;

2.create是静态的,所以也可以称为静态工厂。

3.不方便的是如果要增加一种产品,那么就需要在工厂类里面添加一个判断,扩展性比较差;

4.不同的产品需要不同的参数的时候也是不支持的。

2>另外一种简单工厂(基于反射)

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;
    }
}

在创建具体的产品类的时候,使用反射而不是具体的类型,这样增加或者减少产品时,就不用修改工厂类了;

调用方法

public static void main(String[] args) {
        //兰州拉面
        INoodles lz = StaticNoodlesFactory.createNoodles(LzNoodles.class);
        lz.desc();
        //泡面
        INoodles pm = StaticNoodlesFactory.createNoodles(PaoNoodles.class);
        pm.desc();
    }

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

3>普通工厂

    普通工厂就是把简单工厂的创建过程拆分成一个一个的小工厂,比如生成兰州拉面的定义一个工厂,生产泡面的定义一个工厂;产品类做了抽象,创建过程也做了抽象;具体代码如下

定义一个抽象的生产面条的接口

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

生产干扣面的工厂

public class GankouFactory extends NoodlesFactory {
    @Override
    public INoodles create() {
        return new GankouNoodles();
    }
}
/**
 * 兰州拉面的工厂
 */
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 static void main(String[] args) {
        NoodlesFactory noodlesFactory = new PaoFactory();
        INoodles iNoodles = noodlesFactory.create();
        iNoodles.desc();
    }

    普通工厂比简单工厂要复杂一些,每个对应的产品都有一个具体生产它的小工厂,在这个小工厂中,去创建对应的产品,这样的好处是需求变化的时候,不需要修改已有的类;拥抱变化;

4>多个产品的抽象工厂

    上面介绍的都是单产品的,生产面条,了解下多产品系的,比如客栈,不仅买面条,还有喝的,面条有不同的面条,同样喝的也有不同的类型,可乐,橙汁,雪碧等等;这时候,我们可以抽象出一个饮料的类,然后不同店里面返回不同的饮料;通过一个例子说明;

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();
}
/**
 * KFC
 */
public class KFCFoodFactory extends AbstractFoodFactory {
    @Override
    public INoodles createNoodles() {
        return new PaoNoodles();//KFC居然卖泡面
    }

    @Override
    public IDrinks createDrinks() {
        return new ColaDrinks();//卖可乐
    }
}
/**
 * 兰州拉面
 */
public class LzlmFoodFactory extends AbstractFoodFactory {
    @Override
    public INoodles createNoodles() {
        return new LzNoodles();//卖兰州拉面
    }

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

工厂和产品都做了抽象,面向接口编程,拥抱变化;比如说兰州拉面馆卖可口可乐了,那就返回就好了

@Override
    public IDrinks createDrinks() {
        return new ColaDrinks();
    }


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值