设计模式之工厂模式

简介

工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

简单工厂模式

顾名思义我来举一个小例子,小明与小红去商场玩,小红说“我想吃冰激凌,你快去给我买吧”,小明走到第一个店内,买到的是一个草莓味的冰激凌,拿去给小红,小红说“我不想吃这个口味的,我要吃巧克力的”,那小明又得回去买了,这时可惜了,那家店内刚好没这款卖,小明又跑到另外一家店内买好在回来拿给小红,这个例子我在下面用编码方式来说明一下

优缺点

优点:

  1. 调用对象只需要知道名称即可
  2. 后期扩展方便,如需在增加不同工作,只需添加一个工厂类即可
  3. 屏蔽产品的具体实现,调用者只关心产品的接口

缺点:
每次增加一个产品时,都需要增加一个具体类和对象实现工厂,这样一来还是增加了系统的复杂度

场景

日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方
数据库访问配置:在访问不同的数据库时也可以使用

例子一(未使用工厂模式)

package demo;

/**
 * @Date 2021/7/13 10:55
 * @Version SpringBoot 2.2.2
 * @packageName 草莓味冰激凌
 */
public class Strawberry{

    public void strawberryTest(){
        System.out.println("第一家店:草莓味冰激凌");
    }
}

package demo;

/**
 * @Date 2021/7/13 11:14
 * @Version SpringBoot 2.2.2
 * @packageName 巧克力冰激凌
 */
public class Chocolate {

    public void chocolateTest(){
        System.out.println("第二家店:巧克力冰激凌");
    }
}
package main;

import demo.Chocolate;
import demo.Strawberry;

/**
 * @Date 2021/7/13 10:59
 * @Version SpringBoot 2.2.2
 * @packageName 
 */
public class Main {

    public static void main(String[]args){
        //草莓味
        Strawberry strawberry = new Strawberry();
        strawberry.strawberryTest();
        //巧克力味
        Chocolate chocolate = new Chocolate();
        chocolate.chocolateTest();

        //.....橘子味、西瓜味
    }
}

就如我上所说,要是小红还想吃橘子味、西瓜味的呢?那如是又遇上商家没有的情况岂不是跑的很累吗,这时候小明就去向商场管理员提交了一个建议,说可以在商场放置一台冰激凌机器,而这个机器呢,可以有不同口味,现在你去看门面基本上也是一台冰激凌机器制作多种口味的是吧,那这个机器是什么呢,这个时候就如工厂模式的工厂了,把机器比做工厂来运行,下面我把上面的例子化为工厂实现

例子二(使用工厂模式)

package demo;

/**
 * @Date 2021/7/13 11:48
 * @Version SpringBoot 2.2.2
 * @packageName 出口
 */
public interface Exit {

    void draw();
}
package demo;
/**
 * @Date 2021/7/13 10:55
 * @Version SpringBoot 2.2.2
 * @packageName 草莓味冰激凌
 */
public class Strawberry implements Exit{

    @Override
    public void draw() {
        System.out.println("出口一:草莓味冰激凌");
    }
}
package demo;

/**
 * @Date 2021/7/13 11:14
 * @Version SpringBoot 2.2.2
 * @packageName 巧克力冰激凌
 */
public class Chocolate implements Exit {

    @Override
    public void draw() {
        System.out.println("出口二:巧克力冰激凌");
    }
}
package demo;

/**
 * @Date 2021/7/13 11:50
 * @Version SpringBoot 2.2.2
 * @packageName 机器
 */
public class Machine {

    public Exit getExit(String exit) {
        if (exit.equalsIgnoreCase("草莓")) {
            return new Strawberry();
        } else if (exit.equalsIgnoreCase("巧克力")) {
            return new Chocolate();
        }
        return null;
    }
}
package main;


import demo.Exit;
import demo.Machine;

import java.util.Scanner;

/**
 * @Date 2021/7/13 10:59
 * @Version SpringBoot 2.2.2
 * @packageName
 */
public class Main {

    public static void main(String[]args){
        Scanner input = new Scanner(System.in);
        System.out.println("小红在机器面前选择了:");
        String selector = input.next();
        Machine machine = new Machine();
        switch (selector){
            case "草莓":
                Exit exit = machine.getExit("草莓");
                exit.draw();
                break;
            case "巧克力":
                Exit exit1 = machine.getExit("巧克力");
                exit1.draw();
                break;
        }
    }
}

main方法就当我们在机器选择的出口,后期需要什么口味的直接选择即可,下面我在来说一下工厂模式的实现原理
在这里插入图片描述
当客户在机器面前选择不同口味的冰激凌,这个机器也就是上面的Machine类,选择的时候有出口这个出口就是Eixt()接口,这个接口里存放着不同口味的冰激凌,当需求者选择后方可在不同的类实现中,也就是Chocolate类与Strawberry中吐出想要的冰激凌,这就是简单的工厂模式

抽象工厂模式

接下来机器是解决了出不同口味的冰激凌,但是每个人的食量又不同了吧,这个时候怎么办呢,那就讲一讲抽象工厂模式的作用吧,抽象工厂模式也是创建型模式,只是在简单工厂模式上的复杂程度要高一些,下面带着吃货们的大小中杯来解决这个疑虑,既然名字就叫抽象,那么肯定是用到abstract这个关键词了吧,我们先画一张图,根着这张图的思路往下走着
在这里插入图片描述

根据这个图,我们在刚刚所创建的工厂模式中进行改变,例子我已写好,代码放在下面

package demo;

/**
 * @Date 2021/7/13 11:48
 * @Version SpringBoot 2.2.2
 * @packageName 出口
 */
public interface Exit {

    void draw();
}
package demo;

/**
 * @Date 2021/7/13 11:14
 * @Version SpringBoot 2.2.2
 * @packageName 巧克力冰激凌
 */
public class Chocolate implements Exit {

    @Override
    public void draw() {
        System.out.println("巧克力冰激凌");
    }
}

package demo;

/**
 * @Date 2021/7/13 10:55
 * @Version SpringBoot 2.2.2
 * @packageName 草莓味冰激凌
 */
public class Strawberry implements Exit{

    @Override
    public void draw() {
        System.out.println("草莓味冰激凌");
    }
}

package demo;

/**
 * @Date 2021/7/13 14:57
 * @Version SpringBoot 2.2.2
 * @packageName 规格
 */
public interface Sepc {

    void size();
}

package demo;

/**
 * @Date 2021/7/13 15:01
 * @Version SpringBoot 2.2.2
 * @packageName 小杯
 */
public class Adj implements Sepc {

    @Override
    public void size() {
        System.out.println("小杯");
    }
}
package demo;

/**
 * @Date 2021/7/13 15:00
 * @Version SpringBoot 2.2.2
 * @packageName 中
 */
public class Centre implements Sepc {


    @Override
    public void size() {
        System.out.println("中杯");
    }
}
package demo;

/**
 * @Date 2021/7/13 14:58
 * @Version SpringBoot 2.2.2
 * @packageName 大杯
 */
public class Big implements Sepc {


    @Override
    public void size() {
        System.out.println("大杯");
    }
}

package demo;

import java.util.logging.Logger;

/**
 * @Date 2021/7/13 11:50
 * @Version SpringBoot 2.2.2
 * @packageName 机器
 */
public abstract class Machine {

    public abstract Exit getExit(String exit);

    public abstract Sepc getSepc(String sepc);
}

package demo;

/**
 * @Date 2021/7/13 15:09
 * @Version SpringBoot 2.2.2
 * @packageName 口味实现
 */
public class ExitFactory extends Machine {


    @Override
    public Exit getExit(String exit) {
        if (exit.equalsIgnoreCase("草莓")){
            return new Strawberry();
        }else if (exit.equalsIgnoreCase("巧克力")){
            return new Chocolate();
        }
        return null;
    }

    @Override
    public Sepc getSepc(String sepc) {
        return null;
    }
}

package demo;

/**
 * @Date 2021/7/13 15:20
 * @Version SpringBoot 2.2.2
 * @packageName 规格实现
 */
public class SepcFactory extends Machine {

    @Override
    public Exit getExit(String exit) {
        return null;
    }

    @Override
    public Sepc getSepc(String sepc) {
        if (sepc.equalsIgnoreCase("大杯")){
            return new Big();
        }else if (sepc.equalsIgnoreCase("中杯")){
            return new Centre();
        }else if (sepc.equalsIgnoreCase("小杯")){
            return new Adj();
        }
        return null;
    }
}

package demo;


/**
 * @Date 2021/7/13 15:22
 * @Version SpringBoot 2.2.2
 * @packageName 生成器
 */
public class Production {

    public static Machine getMachine(String machine){
        if (machine.equalsIgnoreCase("exit")){
            return new ExitFactory();
        }else if (machine.equalsIgnoreCase("sepc")){
            return new SepcFactory();
        }
        return null;
    }
}

package main;


import demo.Exit;
import demo.Machine;
import demo.Production;
import demo.Sepc;

import java.util.Scanner;

/**
 * @Date 2021/7/13 10:59
 * @Version SpringBoot 2.2.2
 * @packageName
 */
public class Main {

    public static void main(String[]args){
        Scanner input = new Scanner(System.in);
        System.out.println("口味选择:");
        String selector = input.next();
        Machine machine = Production.getMachine("exit");
        switch (selector){
            case "草莓":
                Exit exit = machine.getExit("草莓");
                exit.draw();
                break;
            case "巧克力":
                Exit exit1 = machine.getExit("巧克力");
                exit1.draw();
                break;
        }
        Machine machine1 = Production.getMachine("sepc");
        System.out.println("规格选择:");
        String secp = input.next();
        switch (secp){
            case "大杯":
                Sepc sp =machine1.getSepc("大杯");
                sp.size();
                break;
            case "中杯":
                Sepc sp1 =machine1.getSepc("中杯");
                sp1.size();
                break;
            case "小杯":
                Sepc sp2 =machine1.getSepc("小杯");
                sp2.size();
                break;
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

藤井大叔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值