工厂模式

0 定义

人们经常说到的工厂模式有三种:简单工厂模式,工厂方法模式和抽象工厂模式.

  • 简单工厂模式:严格来说,它不是一种设计模式,比较像是一种编程习惯,由于经常使用,很多人也会称它为一种设计模式.
  • 工厂方法模式:定义了一个创建对象的接口,但是是由子类来决定实例化那一种对象,将对象实例化推迟到子类.
  • 抽象工厂模式:提供一个接口,用来创建相关或相互依赖对象的家族,而不需要明确指定具体类.

1 简单工厂模式

例如: 当你拥有一家包子铺时,每天早上你需要制作多种多样的包子来出售.这时我们创建的包子铺代码为:

/**
 * @Description: 包子类
 * @author: wangjie
 * @createAt: 2018/8/19-09:56
 */
public class Bun {

    private int size; // 大小

    private int price; // 单价 分

    private int type;// 类型, 馅

    public void prepare(){
        System.out.println("准备阶段,上屉等");
    }

    public void steamBun(){
        System.out.println("蒸包子");
    }

    public void finish(){
        System.out.println("蒸好出笼");
    }

    .....    
}


/**
 * @Description: 包子类型
 * @author: wangjie
 * @createAt: 2018/8/19-10:12
 */
public enum BunEnums {

    CABBAGE_BUN(1,"白菜馅包子"),
    LEEK_BUN(2,"韭菜馅包子"),
    ;
    public int type ;
    private String desc;

    BunEnums( int type, String desc ) {
        this.type = type;
        this.desc = desc;
    }

    public int getType() {
        return type;
    }

    public String getDesc() {
        return desc;
    }
}


/**
 * @Description: 白菜馅包子
 * @author: wangjie
 * @createAt: 2018/8/19-10:09
 */
public class CabbageBun extends Bun {
    // 制作白菜馅
}

/**
 * @Description: 韭菜馅包子
 * @author: wangjie
 * @createAt: 2018/8/19-10:14
 */
public class LeekBun extends Bun {
    //制作韭菜馅
}



/**
 * @Description: 包子铺业务类
 * @author: wangjie
 * @createAt: 2018/8/19-10:01
 */
public class BunStoreService {

    /**
     * 1 下单,购买包子
     * @param bunType
     * @return
     */
    public Bun orderBun(int bunType){
        Bun bun = null;

        if (BunEnums.CABBAGE_BUN.getType() == bunType){
            bun = new CabbageBun();
        }else if (BunEnums.LEEK_BUN.getType() == bunType){
            bun = new LeekBun();
        }

        bun.prepare(); // 上屉
        bun.steamBun();// 蒸
        bun.finish(); // 完成,出笼

        return bun;
    }
}

当有人来购买包子时(假设为现场制作),包子铺根据他提供的类型来创建包子对象,并将它需要的包子对象返回.
随着包子铺的扩张,包子铺可能还提供猪肉馅,粉丝馅等其他馅包子.这时我们的BunEnums需要扩展,BunStoreService.orderBun(int bunType)需要修改.修改后代码如下:

/**
 * @Description: 包子铺业务类
 * @author: wangjie
 * @createAt: 2018/8/19-10:01
 */
public class BunStoreService {

    /**
     * 1 下单,购买包子
     * @param bunType
     * @return
     */
    public Bun orderBun(int bunType){
        Bun bun = null;

        if (BunEnums.CABBAGE_BUN.getType() == bunType){
            bun = new CabbageBun();
        }else if (BunEnums.LEEK_BUN.getType() == bunType){
            bun = new LeekBun();
        }
        // do add by 汪杰 at 2018/8/19 10:35  Reason: 包子铺扩展,添加了包子类型
        else if (BunEnums.PORK_BUN.getType() == bunType){
            bun = new PorkBun();
        }else if (BunEnums.RICE_NOODLES_BUN.getType() == bunType){
            bun = new RiceNoodlesBun();
        }
        // do add end
        

        bun.prepare(); // 上屉
        bun.steamBun();// 蒸
        bun.finish(); // 完成,出笼

        return bun;
    }
}

随着包子铺不断的扩张,包子类型不断添加,下单购买包子的业务代码需要不但的修改.
但是,事实上下单购买的流程是不变的,变动的是制作包子的过程.
我们知道了哪些是可变的,哪些是不变的,根据 对扩展开放,对修改关闭 的原则,将可变动的代码封装到一起.
我们可以使用一个新的对象,由它来负责创建包子对象,我们可以称这个新的对象为 “工厂”.

/**
 * @Description: 简单工厂
 * @author: wangjie
 * @createAt: 2018/8/19-10:50
 */
public class SimpleBunfactory {
    /**
     * 创建包子对象
     * @param bunType 包子类型
     * @return bun
     */
    public Bun createBun(int bunType){
        Bun bun = null;
        if (BunEnums.CABBAGE_BUN.getType() == bunType){
            bun = new CabbageBun();
        }else if (BunEnums.LEEK_BUN.getType() == bunType){
            bun = new LeekBun();
        }else if (BunEnums.PORK_BUN.getType() == bunType){
            bun = new PorkBun();
        }else if (BunEnums.RICE_NOODLES_BUN.getType() == bunType){
            bun = new RiceNoodlesBun();
        }
        return  bun;
    }
    /**
     * 创建包子对象
     * 
     * 利用静态方法定义一个工厂,这种方法很常见,经常被称为 静态工厂
     * 优点: 在业务类中不需要实例化工厂对象就可以用来实例化对象
     * 缺点: 不能通过继承来改变创建实例化的方法和行为.
     * 
     * @param bunType 包子类型
     * @return bun
     */
    public static Bun createBunByType(int bunType){
        Bun bun = null;
        if (BunEnums.CABBAGE_BUN.getType() == bunType){
            bun = new CabbageBun();
        }else if (BunEnums.LEEK_BUN.getType() == bunType){
            bun = new LeekBun();
        }else if (BunEnums.PORK_BUN.getType() == bunType){
            bun = new PorkBun();
        }else if (BunEnums.RICE_NOODLES_BUN.getType() == bunType){
            bun = new RiceNoodlesBun();
        }
        return  bun;
    }
}

包子铺的业务类改为


/**
 * @Description: 包子铺业务类
 * @author: wangjie
 * @createAt: 2018/8/19-10:01
 */
public class BunStoreService {

    SimpleBunfactory simpleBunfactory;

    public BunStoreService(SimpleBunfactory simpleBunfactory){
        this.simpleBunfactory = simpleBunfactory;
    }


    /**
     * 1 下单,购买包子
     * @param bunType
     * @return
     */
    public Bun orderBun(int bunType){
        Bun bun = simpleBunfactory.createBun(bunType);
        //Bun bun = SimpleBunfactory.createBunByType(bunType);

        bun.prepare(); // 上屉
        bun.steamBun();// 蒸
        bun.finish(); // 完成,出笼

        return bun;
    }
}

此时.我们就已经完成了使用 “简单工厂模式” 来创建对象,
我们将创建包子对象的代码封装到了一个类,当以后包子铺的包子类型在扩展或某种包子下线时,就只需要修改这一个地方.
有人会觉得,之前在orderBun(int bunType)方法中创建对象,当扩展时,也只需要修改一处,为什么还需要这么麻烦呢?
我们将集体的实例化包子对象的代码从下单流程中抽离出来,对扩展开发,对修改关闭

2 工厂方法模式

可能每一种包子都由指定的师傅制作.张师傅制作白菜馅包子,李师傅制作韭菜包子.这时整个包子厂就是一个父工厂类,张师傅/李师傅就是有两个子工厂类.

工厂类

/**
 * 包子工厂
 * @AUTHOR 汪杰
 * @CREATE 2018/11/13 16:46
 */
public interface BunFactory {
    <T extends Bun> T createBun();
}


/**
 * @Description: 白菜包工厂
 * @author: wangjie
 * @createAt: 2019/3/28-22:22
 */
public class CabageBunFactory implements BunFactory {

    @Override
    public CabbageBun createBun() {
        return new CabbageBun();
    }
}

/**
 * @Description: 韭菜包工厂
 * @author: wangjie
 * @createAt: 2019/3/28-22:22
 */
public class LeekBunFactory implements BunFactory {
    @Override
    public LeekBun createBun() {
        return new LeekBun();
    }
}

包子实体类


/**
 * @Description: 包子
 * @author: wangjie
 * @createAt: 2019/3/28-22:54
 */
public interface Bun {
}


/**
 * @Description: 包子类
 * @author: wangjie
 * @createAt: 2019/3/28-22:19
 */
public abstract class AbstractBun implements Bun ,Serializable{


    public void prepare(){
        System.out.println("准备阶段,上屉等");
    }

    public void steamBun(){
        System.out.println("蒸包子");
    }

    public void finish(){
        System.out.println("蒸好出笼");
    }

}


/**
 * @Description: 白菜馅包子
 * @author: wangjie
 * @createAt: 2018/8/19-10:09
 */
public class CabbageBun extends AbstractBun {
}

/**
 * @Description: 韭菜馅包子
 * @author: wangjie
 * @createAt: 2018/8/19-10:14
 */
public class LeekBun extends AbstractBun {
}

当包子店的生意越来越好,两种口味的包子不能满足客户的需要时,老板可能就会引进新的口味的包子,新请一个王师傅制作猪肉馅包子.遇到这种情况,代码中只需要新建一个工厂和一个包子实例.

/**
 * @Description: 猪肉馅包子工厂
 * @author: wangjie
 * @createAt: 2019/3/28-22:49
 */
public class PorkBunFactory implements BunFactory {
    @Override
    public PorkBun createBun() {
        return new PorkBun();
    }
}


/**
 * @Description: 猪肉馅包子
 * @author: wangjie
 * @createAt: 2019/3/28-22:48
 */
public class PorkBun extends AbstractBun {
}

工厂方法模式是简单工厂模式的衍生,解决了许多简单工厂模式的问题.

  • 1 完全实现"开-闭原则",实现了可扩展;
  • 2 更复杂的层次结构,可以应用于产品结构复杂的场合;
  • 3 基类为工厂方法提供缺省实现,子类可以重写新的实现;也可以继承父类的实现.加一层间接性,增加了代码灵活性;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值