简单易懂的“讲”设计模式中的工厂模式(Factory)

本文深入探讨了工厂模式的三种变体:静态工厂模式、简单工厂模式和工厂方法模式,通过一个生动的“卖肉夹馍”案例,展示了如何根据不同需求创建和使用产品。同时,文章还介绍了抽象工厂模式,说明了如何在多个相关产品族中保持一致性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文:https://blog.youkuaiyun.com/lmj623565791/article/details/24460585 

设计模式分为3种类型,共23种。

创建型模式: 单例模式 ,抽象工厂模式,  建造者模式 , 工厂模式, 原型模式

结构型模式: 适配器模式, 桥接模式 ,装饰模式 ,组合模式,外观模式 ,享元模式, 代理模式。

行为型模式:模板方式模式, 命令模式, 迭代器模式, 观察者模式 ,中介者模式 ,备忘录模式,解释器模式,状态模式,

                      策略模式,职责链模式 访问者模式。

下面这篇文章围绕工厂模式展开。

工厂模式中主要包括 静态工厂模式 简单工厂模式 工厂方法模式 抽象工厂模式。

本篇文章主要参考张鸿洋博客展开 仿照他写的博客写了一个例子,边看边写,印象会更深一点。

目录

1.静态工厂模式

2.简单工厂模式(常见)

3.工厂方法模式

4.抽象方法模式


1.静态工厂模式

这个比较常见,项目中的辅助类,TextUtil.isEmpty (类+静态方法)

2.简单工厂模式(常见

接下来我们将围绕简单工厂模式展开一个“卖肉夹馍”的例子。

2.1 准备一个生产肉夹馍的工厂。

2.2 拥有一个生产肉夹馍的工厂以后,我们需要一个卖肉夹馍的店

2.3 接下来就是各种各样的肉夹馍了

代码中所有的类:

这样一种方式的好处就是卖肉夹馍的店只要专心卖肉夹馍 ,制作肉夹馍的工厂专心做肉夹馍。即使增加或者减少肉夹馍的种类也与卖肉夹馍的店无关。

2.1 RouJiaMo

package com.soup.redis.common;

/**
 * @Author tanghh
 * @Date 2020/7/17 14:48
 */
public abstract class RouJiaMo {
    protected String name;

    /**
     * 准备工作
     */
    public void prepare() {
        System.out.println("揉面-剁肉-完成准备工作");
    }

    /**
     * 使用你们的专用袋-包装
     */
    public void pack() {
        System.out.println("肉夹馍-专用袋-包装");
    }

    /**
     * 秘制设备-烘烤2分钟
     */
    public void fire() {
        System.out.println("肉夹馍-专用设备-烘烤");
    }

}

2.2 各种风味的肉夹馍

package com.soup.redis.common;

/**
 * @Author tanghh
 * @Date 2020/7/17 14:50
 */
public class LaRouJiaMo extends  RouJiaMo {
    public LaRouJiaMo(){
        this.name = "辣味肉夹馍";
    }
}
package com.soup.redis.common;

/**
 * @Author tanghh
 * @Date 2020/7/17 14:53
 */
public class SuanRouJiaMo extends RouJiaMo {
    public SuanRouJiaMo(){
        this.name = "酸味肉夹馍";
    }
}
package com.soup.redis.common;

/**
 * @Author tanghh
 * @Date 2020/7/17 14:51
 */
public class TianRouJiaMo extends RouJiaMo {
    public TianRouJiaMo (){
        this.name = "甜味肉夹馍";
    }
}

2.3 制作肉夹馍的工厂

package com.soup.redis.factory;

import com.soup.redis.common.LaRouJiaMo;
import com.soup.redis.common.RouJiaMo;
import com.soup.redis.common.SuanRouJiaMo;
import com.soup.redis.common.TianRouJiaMo;

/**
 * @Author tanghh
 * @Date 2020/7/17 14:46
 */
public class SimpleRouJiaMoFactory {
    public RouJiaMo createRouJiaMo(String type) {
        RouJiaMo rouJiaMo = null;

        if (type.equals("Suan")) {
            System.out.println("酸味肉夹馍");
            rouJiaMo = new SuanRouJiaMo();
        } else if (type.equals("Tian")) {
            System.out.println("甜味肉夹馍");
            rouJiaMo = new TianRouJiaMo();
        } else if (type.equals("La")) {
            System.out.println("辣味肉夹馍");
            rouJiaMo = new LaRouJiaMo();
        }
        return rouJiaMo;
    }


}

2.4 卖肉夹馍的店 

package com.soup.redis.store;

import com.soup.redis.common.RouJiaMo;
import com.soup.redis.factory.SimpleRouJiaMoFactory;

/**
 * @Author tanghh
 * 卖肉夹馍的店
 * @Date 2020/7/17 14:54
 */
public  class RoujiaMoStore {

    /**
     * 根据传入类型卖不同的肉夹馍
     *
     * @param type
     * @return
     */
    public RouJiaMo sellRouJiaMo(String type) {
        SimpleRouJiaMoFactory factory = new SimpleRouJiaMoFactory();
        RouJiaMo rouJiaMo = factory.createRouJiaMo(type);
        rouJiaMo.prepare();
        rouJiaMo.fire();
        rouJiaMo.pack();
        return rouJiaMo;
    }

}
package com.soup.redis.test;

import com.soup.redis.store.RoujiaMoStore;

/**
 * @Author tanghh
 * @Date 2020/7/17 14:58
 */
public class FactoryTest {
    public static void main(String[]args){
     //卖肉夹馍
        RoujiaMoStore store = new RoujiaMoStore();
        store.sellRouJiaMo("La");
    }
}

 

 

3.工厂方法模式

定义:定义一个创建对象的的接口,但由子类决定要实例化的类是哪一个,工厂方法模式把类实例化的过程推迟到子类。

接下来建立一个开连锁店的例子,此时我们在西安开一个分店。总店在上海。

工厂模式方式跟简单工厂模式不一样的地方在于 子类来决定生产什么类型的肉夹馍,总店提供秘方,而且分店总数一多的话,简单工厂模式里面的工厂里面的if就太多了。

3.1 定义一个卖肉夹馍的店,总店提供生产肉夹馍的方法。

3.2 西安开了一个分店,得到总店的生成肉夹馍的方法以后,就自己制作属于自己的肉夹馍。

例子涉及的所有类:

 

3.1 生产肉夹馍的总店

package com.soup.redis.store;

import com.soup.redis.common.RouJiaMo;

/**
 * @Author tanghh
 * 卖肉夹馍的店
 * @Date 2020/7/17 14:54
 */
public abstract class RoujiaMoStore {
    /**
     * 创建肉夹馍的方法
     * @param type
     * @return
     */
    public abstract RouJiaMo createRouJiaMo(String type);
    /**
     * 根据传入类型卖不同的肉夹馍
     *
     * @param type
     * @return
     */
    public RouJiaMo sellRouJiaMo(String type) {
        //制作肉夹馍
        RouJiaMo rouJiaMo = createRouJiaMo(type);
        rouJiaMo.prepare();
        rouJiaMo.fire();
        rouJiaMo.pack();
        return rouJiaMo;
    }

}

3.2 西安的肉夹馍分店

package com.soup.redis.store;

import com.soup.redis.common.RouJiaMo;
import com.soup.redis.common.XianLaRouJiaMo;
import com.soup.redis.common.XianSuanRouJiaMo;
import com.soup.redis.common.XianTianRouJiaMo;

/**
 * @Author tanghh
 * @Date 2020/7/17 15:16
 * 西安卖肉夹馍的店
 */
public class XianRouJiaMoStore extends RoujiaMoStore {

    @Override
    public RouJiaMo createRouJiaMo(String type) {
        RouJiaMo rouJiaMo = null;
        if (type.equals("Suan")) {
            System.out.println("西安酸味肉夹馍");
            rouJiaMo = new XianSuanRouJiaMo();
        } else if (type.equals("Tian")) {
            System.out.println("西安甜味肉夹馍");
            rouJiaMo = new XianTianRouJiaMo();
        } else if (type.equals("La")) {
            System.out.println("西安辣味肉夹馍");
            rouJiaMo = new XianLaRouJiaMo();
        }
        return rouJiaMo;
    }
}

3.3 各种风味的具有西安特色的肉夹馍 

package com.soup.redis.common;

/**
 * @Author tanghh
 * @Date 2020/7/17 14:48
 */
public abstract class RouJiaMo {
    protected String name;

    /**
     * 准备工作
     */
    public void prepare() {
        System.out.println("揉面-剁肉-完成准备工作");
    }

    /**
     * 使用你们的专用袋-包装
     */
    public void pack() {
        System.out.println("肉夹馍-专用袋-包装");
    }

    /**
     * 秘制设备-烘烤2分钟
     */
    public void fire() {
        System.out.println("肉夹馍-专用设备-烘烤");
    }

}
package com.soup.redis.common;


/**
 * @Author tanghh
 * @Date 2020/7/17 15:19
 */
public class XianLaRouJiaMo extends RouJiaMo {
    public XianLaRouJiaMo (){
        this.name = "西安辣味肉夹馍";
    }
}

 

package com.soup.redis.common;


/**
 * @Author tanghh
 * @Date 2020/7/17 15:18
 */
public class XianSuanRouJiaMo extends RouJiaMo {
    public XianSuanRouJiaMo(){
        this.name="西安的酸味肉夹馍";
    }
}
package com.soup.redis.common;


/**
 * @Author tanghh
 * @Date 2020/7/17 15:22
 */
public class XianTianRouJiaMo extends RouJiaMo {
    public XianTianRouJiaMo(){
        this.name = "西安的甜味肉夹馍";
    }
}

 

4.抽象方法模式

定义:提供一个接口,用于创建相关的或依赖对象的家族,而不需要明确指定具体类。

接着上面连锁店的例子来说,为了建立一个良好的品牌形象,公司决定在各个城市建立自己的原料厂,保证高质量原料的供应。

4.1 总公司新建一个提供原料的生产接口, 西安分店根据当地特色提供材料。

4.2 接下来修改肉夹馍生产接口,肉夹馍中的肉 ,调料都需要调用总店的原料。

4.3 最后测试。

例子所涉及的代码和类:

4.1 总公司新建一个提供原料的生产接口, 西安分店根据当地特色提供材料。

package com.soup.redis.factory;

import com.soup.redis.common.Meat;
import com.soup.redis.common.YuanLiao;

/**
 * @Author tanghh
 * @Date 2020/7/17 15:44
 */
public interface RouJiaMoYLFactroy {

    /**
     * 生产肉
     * @return
     */
     Meat createMeat();

    /**
     * 生产调料神马的
     * @return
     */
     YuanLiao createYuanliao();



}
package com.soup.redis.factory;

import com.soup.redis.common.FreshMeat;
import com.soup.redis.common.LaWeiYuanLiao;
import com.soup.redis.common.Meat;
import com.soup.redis.common.YuanLiao;

/**
 * @Author tanghh
 * @Date 2020/7/17 15:45
 */
public class XianRouJiaMoYLFactroy implements RouJiaMoYLFactroy {
    @Override
    public Meat createMeat() {
        return new FreshMeat();
    }

    @Override
    public YuanLiao createYuanliao() {
        return new LaWeiYuanLiao();
    }
}

4.2 接下来修改肉夹馍生产接口,肉夹馍中的肉 ,调料都需要调用总店的原料。

package com.soup.redis.common;

import com.soup.redis.factory.RouJiaMoYLFactroy;

/**
 * @Author tanghh
 * @Date 2020/7/17 14:48
 */
public abstract class RouJiaMo {
    public String name;

    /**
     * 准备工作
     *
     * @param ylFactroy
     */
    public final void prepare(RouJiaMoYLFactroy ylFactroy) {
        Meat meat = ylFactroy.createMeat();
        YuanLiao yuanliao = ylFactroy.createYuanliao();
        System.out.println("使用官方的原料" + meat.name + " , " + yuanliao.name + "作为原材料制作肉夹馍 ");
    }

    /**
     * 使用你们的专用袋-包装
     */
    public final void pack() {
        System.out.println("肉夹馍-专用袋-包装");
    }

    /**
     * 秘制设备-烘烤2分钟
     */
    public final void fire() {
        System.out.println("肉夹馍-专用设备-烘烤");
    }


}

 卖肉夹馍的店

package com.soup.redis.store;

import com.soup.redis.common.RouJiaMo;

/**
 * @Author tanghh
 * @Date 2020/7/17 15:52
 */
public abstract class RoujiaMoStore {
    public abstract RouJiaMo createRouJiaMo(String type);

    /**
     * 根据传入类型卖不同的肉夹馍
     *
     * @param type
     * @return
     */
    public abstract RouJiaMo sellRouJiaMo(String type);



}
package com.soup.redis.store;

import com.soup.redis.common.*;
import com.soup.redis.factory.RouJiaMoYLFactroy;

/**
 * @Author tanghh
 * @Date 2020/7/17 15:52
 */
public class XianRouJiaMoStore extends RoujiaMoStore {
    @Override
    public RouJiaMo createRouJiaMo(String type)
    {
        RouJiaMo rouJiaMo = null;
        if (type.equals("Suan"))
        {
            rouJiaMo = new XianSuanRouJiaMo();

        } else if (type.equals("Tian"))
        {
            rouJiaMo = new XianTianRouJiaMo();
        } else if (type.equals("La"))
        {
            rouJiaMo = new XianLaRouJiaMo();
        }
        return rouJiaMo;

    }

    @Override
    public RouJiaMo sellRouJiaMo(String type) {
       RouJiaMo rouJiaMo = createRouJiaMo(type);
        RouJiaMoYLFactroy ylFactroy = new RouJiaMoYLFactroy() {
            @Override
            public Meat createMeat() {
                return new FreshMeat();
            }

            @Override
            public YuanLiao createYuanliao() {
                return new LaWeiYuanLiao();
            }
        };
        rouJiaMo.prepare(ylFactroy);
        rouJiaMo.fire();
        rouJiaMo.pack();
        return rouJiaMo;
    }

}

 

4.3 测试

package com.soup.redis.test;

import com.soup.redis.common.RouJiaMo;
import com.soup.redis.store.RoujiaMoStore;
import com.soup.redis.store.XianRouJiaMoStore;

/**
 * @Author tanghh
 * @Date 2020/7/17 14:58
 */
public class FactoryTest {
    public static void main(String[] args) {
        //西安分店卖肉夹馍
        RoujiaMoStore roujiaMoStore = new XianRouJiaMoStore();
        RouJiaMo suanRoujiaMo = roujiaMoStore.sellRouJiaMo("Suan");
        System.out.println(suanRoujiaMo.name);



    }
}

抽象方法模式到这就结束了,

 

 

最后这部分补充一下代码

package com.soup.redis.common;

/**
 * @Author tanghh
 * @Date 2020/7/17 15:46
 */
public abstract class Meat {
    protected String name;
}
package com.soup.redis.common;

/**
 * @Author tanghh
 * @Date 2020/7/17 15:47
 */
public class FreshMeat extends Meat {
    public FreshMeat(){
        this.name = "新鲜的肉";
    }
}
package com.soup.redis.common;

/**
 * @Author tanghh
 * @Date 2020/7/17 15:46
 */
public abstract class YuanLiao {
    protected String name;
}
package com.soup.redis.common;

/**
 * @Author tanghh
 * @Date 2020/7/17 15:47
 */
public class LaWeiYuanLiao extends YuanLiao{
    public LaWeiYuanLiao(){
        this.name = "辣味原料";
    }
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值