简单工厂模式和抽象工厂模式

简单工厂模式和抽象工厂模式

不BB,直接来需求设计

一个披萨店现在需要生产多种颜色的披萨供顾客使用,我们为了满足生产多种颜色的披萨生产,脑海里面第一想法是使用工厂模式来创建不同的披萨。

先看草图的大致设计

在这里插入图片描述
那么想要图中的功能。至少需要3个类。一个是绿颜色披萨实体类,红颜色披萨实体类,还有一个披萨工厂类(我这里将披萨的实体类做了一下继承,多加了一个类)。

披萨拥有名字,颜色,价格,描述

@Data 注解来自于lombok,可以减少set,get,toString方法的编写,但是还是能够使用这些方法

package cn.withme.pattern.abstractFactory.simple;

import lombok.Data;

import java.util.List;

@Data 
public class Pissa {
    protected String name ;
    protected List<String> colors;
    protected Double price;

    public String getDesc () {
        return null;
    }
}

package cn.withme.pattern.abstractFactory.simple;

import cn.withme.pattern.abstractFactory.enums.ColorEnum;
import lombok.Data;

import java.util.Arrays;

/**
 * @className: GreenPissa
 * @description: 绿色披萨
 * @author: liming
 * @date: 2020/1/16
 **/
@Data
public class GreenPissa extends  Pissa{

    public GreenPissa() {
        this.colors = Arrays.asList(ColorEnum.GREEN.getDesc());
        this.name = "一个包含"+this.colors+"的披萨";
        this.price = 10.0;
    }

    @Override
    public String getDesc () {
        return this.name+",\t 价格:"+this.price;
    }
}

package cn.withme.pattern.abstractFactory.simple;

import cn.withme.pattern.abstractFactory.enums.ColorEnum;
import lombok.Data;

import java.util.Arrays;

/**
 * @className: GreenPissa
 * @description: 绿色披萨
 * @author: liming
 * @date: 2020/1/16
 **/
@Data
public class RedPissa extends  Pissa{

    public RedPissa() {
        this.colors = Arrays.asList(ColorEnum.RED.getDesc());
        this.name = "一个包含"+this.colors+"的披萨";
        this.price = 10.0;
    }

    @Override
    public String getDesc () {
        return this.name+",\t 价格:"+this.price;
    }
}

package cn.withme.pattern.abstractFactory.enums;

/**
 * @Description: 颜色枚举类
 * @Author: liming
 * @date 2020年01月16日
 */
public enum ColorEnum {
    RED("red","红色"),
    GREEN("green","绿色"),
    ;

    private String code;
    private String desc ;

    ColorEnum(String code, String desc) {
        this.code = code;
        this.desc = desc;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }

    public static String getTypeNameByType (String type){
        for (ColorEnum c : ColorEnum.values()) {
            if (c.getCode().equalsIgnoreCase(type)) {
                return c.getDesc();
            }
        }
        return null;
    }
}

披萨生产工厂,这里通过create方法,可以生成不同颜色的披萨

package cn.withme.pattern.abstractFactory.simple;

/**
 * @className: PissaFactory
 * @description: 简单的披萨生产工厂
 * @author: liming
 * @date: 2020/1/16
 **/
public class PissaFactory {

    public Pissa create(String type) {
        Pissa p;
        switch (type) {
            case "green":
                p = new GreenPissa();
                break;
            case "red":
                p = new RedPissa();
                break;
             //省略n个case
            default:
                p = new Pissa();
        }
        return p;
    }
}

测试一下

package cn.withme.pattern.abstractFactory.simple;

/**
 * @className: SimplePissaTest
 * @description: 披萨测试
 * @author: liming
 * @date: 2020/1/16
 **/
public class SimplePissaTest {

    public static void main(String[] args) {
        PissaFactory factory = new PissaFactory();
        Pissa pissa = factory.create("red");
        print(pissa); //一个包含[红色]的披萨,	 价格:10.0
    }

    private static void print(Pissa pissa) {
        System.out.println(null == pissa ? "" :pissa.getDesc());
    }
}

那么最简单的披萨生产工厂就已经实现了。

如果觉得if lese 和 switch case,那么可以将PissaFactory修改一下。

package cn.withme.pattern.abstractFactory.simple;

import java.util.HashMap;
import java.util.Map;

/**
 * @className: PissaFactory
 * @description: 简单的披萨生产工厂
 * @author: liming
 * @date: 2020/1/16
 **/
public class PissaFactory {

    private static final Map<String,Pissa> pissaMap = new HashMap<>();

    static {
        pissaMap.put("green", new GreenPissa());
        pissaMap.put("red", new RedPissa());
    }

    public Pissa create(String type) {
       return pissaMap.get(type);
    }

}

这样就省略了if lese 和 switch case

后面披萨店的生意越来越好,全国许多加盟商都来投资。

于是又开始生产披萨。

由于加盟商越来越多,原来的披萨店不能满足各地的顾客需求。所以加盟商们想在自己的区域可以加一些自己的东西。

于是乎苦逼的程序员们开始加班改。

如果单纯的修改这一块的代码

 switch (type) {
            case "green":
                p = new GreenPissa();
                break;
            case "red":
                p = new RedPissa();
                break;
             //省略n个case
            default:
                p = new Pissa();
        }

那么势必这一块的代码会越来越多,而且如果有长沙的加盟商生产红色的披萨,但是需要打上"长沙"两个字标签,广州的加盟商生产红色的披萨,但是需要打上"广州"两个字标签。

目前的设计已经不能满足披萨的生产需求了。

因为原来的披萨生产工厂范围太大了。所以现在必须所有披萨生产的范围,简而言之就是某个地区的加盟商就生产自己那个地区的披萨。互不影响才对。

理想设计如下:

在这里插入图片描述

由于需要带上标签。所以加一个标签枚举类

package cn.withme.pattern.abstractFactory.enums;

/**
 * @Description: 位置枚举类
 * @Author: liming
 * @date 2020年01月16日
 */
public enum LocationEnum {
    CHANGSHA("changsha","长沙"),
    GUANGZHOU("guangzhou","广州"),
    ;

    private String code;
    private String desc ;

    LocationEnum(String code, String desc) {
        this.code = code;
        this.desc = desc;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }

    public static String getTypeNameByType (String type){
        for (LocationEnum c : LocationEnum.values()) {
            if (c.getCode().equalsIgnoreCase(type)) {
                return c.getDesc();
            }
        }
        return null;
    }
}

//这个类 是 长沙加盟商和广东加盟商的父类,如果后续有其他的加盟商加进来,可以直接继承这个类就好了

package cn.withme.pattern.abstractFactory.advance.factory;

import cn.withme.pattern.abstractFactory.advance.domain.Pissa;

/**
 * @className: PissaAbstractFactory
 * @description: 抽象披萨工厂
 * @author: liming
 * @date: 2020/1/16
 **/
public abstract class PissaAbstractFactory {
    abstract Pissa create(String type);
}

长沙加盟商和广东加盟商工厂如下:

package cn.withme.pattern.abstractFactory.advance.factory;

import cn.withme.pattern.abstractFactory.advance.domain.ChangshaGreenPissa;
import cn.withme.pattern.abstractFactory.advance.domain.ChangshaRedPissa;
import cn.withme.pattern.abstractFactory.advance.domain.Pissa;
import cn.withme.pattern.abstractFactory.enums.LocationEnum;

/**
 * @className: ChangshaPissaFactory
 * @description:
 * @author: liming
 * @date: 2020/1/16
 **/
public class ChangshaPissaFactory extends PissaAbstractFactory{

    public static String LOCALTION = LocationEnum.CHANGSHA.getDesc();


    @Override
    Pissa create(String type) {
        Pissa p;
        switch (type) {
            case "green":
                p = new ChangshaGreenPissa();
                break;
            case "red":
                p = new ChangshaRedPissa();
                break;
            //省略n个case
            default:
                p = new Pissa();
        }
        return p;
    }
}

package cn.withme.pattern.abstractFactory.advance.factory;

import cn.withme.pattern.abstractFactory.advance.domain.GuangzhouGreenPissa;
import cn.withme.pattern.abstractFactory.advance.domain.GuangzhouRedPissa;
import cn.withme.pattern.abstractFactory.advance.domain.Pissa;
import cn.withme.pattern.abstractFactory.enums.LocationEnum;

/**
 * @className: ChangshaPissaFactory
 * @description:
 * @author: liming
 * @date: 2020/1/16
 **/
public class GuangZhouPissaFactory extends PissaAbstractFactory{

    public static String LOCALTION = LocationEnum.GUANGZHOU.getDesc();

    @Override
    Pissa create(String type) {
        Pissa p;
        switch (type) {
            case "green":
                p = new GuangzhouGreenPissa();
                break;
            case "red":
                p = new GuangzhouRedPissa();
                break;
            //省略n个case
            default:
                p = new Pissa();
        }
        return p;
    }
}

原来的PissaFactory改成:

package cn.withme.pattern.abstractFactory.advance.factory;


import cn.withme.pattern.abstractFactory.advance.domain.Pissa;

/**
 * @className: PissaFactory
 * @description: 简单的披萨生产工厂
 * @author: liming
 * @date: 2020/1/16
 **/
public class PissaFactory {

    private PissaAbstractFactory abstractFactory;

    public PissaFactory(PissaAbstractFactory abstractFactory) {
        this.abstractFactory = abstractFactory;
    }

    public Pissa create(String type) {
        Pissa pissa = abstractFactory.create(type);
        return pissa;
    }
}

ChangshaGreenPissa,ChangshaRedPissa,GuangzhouGreenPissa,GuangzhouRedPissa 这几个类变化不大,贴一个类,其余的差不多

package cn.withme.pattern.abstractFactory.advance.domain;

import cn.withme.pattern.abstractFactory.advance.factory.ChangshaPissaFactory;
import cn.withme.pattern.abstractFactory.enums.ColorEnum;
import lombok.Data;

import java.util.Arrays;

/**
 * @className: GreenPissa
 * @description: 绿色披萨
 * @author: liming
 * @date: 2020/1/16
 **/
@Data
public class ChangshaGreenPissa extends  Pissa{

    public ChangshaGreenPissa() {
        this.colors = Arrays.asList(ColorEnum.GREEN.getDesc());
        this.name = "一个包含"+this.colors+"的披萨";
        this.price = 10.0;
    }

    @Override
    public String getDesc () {
        return this.name+",\t 价格:"+this.price+",\t 生产地点位于:" + ChangshaPissaFactory.LOCALTION;
        //这里增加了生产位置
    }
}

那么这么一改造的话。后续来再多的加盟商都可以适配这个模式。

写一个测试类试下:

package cn.withme.pattern.abstractFactory.advance;

import cn.withme.pattern.abstractFactory.advance.domain.Pissa;
import cn.withme.pattern.abstractFactory.advance.factory.GuangZhouPissaFactory;
import cn.withme.pattern.abstractFactory.advance.factory.PissaFactory;

/**
 * @className: AdvancePissaFactory
 * @description: 测试类
 * @author: liming
 * @date: 2020/1/16
 **/
public class AdvancePissaFactoryTest {

    public static void main(String[] args) {
        PissaFactory pissaFactory = new PissaFactory(new GuangZhouPissaFactory());
        Pissa pissa = pissaFactory.create("red");
        System.out.println(pissa.getDesc());
    }
}

这样就能改最小的代码,又可以适配不同的加盟商(产品)。

总结一下:简单工厂模式和抽象工厂模式的区别

简单工厂模式对于生成少量的对象来说有好处,但是没有办法做区分多产品(如果要在简单工厂模式里面区分产品也是可以的,只不过会带来更多的if else

而且鲁迅说过,太多的人修改同一个类的话,肯定会把别人的改错,如果每一个加盟商只维护自己的那一部分功能,出错的概率也会相对减少,影响面也不会扩散到其他的加盟商)

代码已上传github(github主页:https://github.com/q920447939/java-study)
代码地址:https://github.com/q920447939/java-study/tree/master/java-bases/src/main/java/cn/withme/pattern/abstractFactory

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值