Java设计模式 | 简单工厂模式

在这里插入图片描述

概述

需求

设计一个咖啡店点餐系统
设计一个咖啡类(Coffee);并定义其两个子类(美式咖啡AmericanCoffee和拿铁咖啡LatteCoffee);再设计一个咖啡店类(CoffeeStore),其具备点咖啡的功能。

类图

image.png

咖啡类
public abstract class Coffee {

    // 获取咖啡名
    public abstract String getName();

    // 加糖
    public void addSugar(){
        System.out.println("加糖");
    }

    // 加奶
    public void addMilk(){
        System.out.println("加奶");
    }
}

美式咖啡类
public class AmericanCoffee extends Coffee {
    @Override
    public String getName() {
        return "美式咖啡";
    }
}

拿铁咖啡类
public class LatteCoffee extends Coffee {
    @Override
    public String getName() {
        return "拿铁咖啡";
    }
}

咖啡店类
public class CoffeeStore {

    public Coffee orderCoffee(String type) {
        // 根据类型创建咖啡实例
        Coffee coffee = null;
        if("Latte".equals(type)) {
            coffee = new LatteCoffee();
        }
        else if("Americano".equals(type)) {
            coffee = new AmericanCoffee();
        }
        else {
            System.out.println("Sorry, we don't have this kind of coffee.");
        }

        // 加糖和奶
        coffee.addSugar();
        coffee.addMilk();

        return coffee;
    }
}
测试
public class Client {
    public static void main(String[] args) {
        // 1 创建咖啡店类
        CoffeeStore coffeeStore = new CoffeeStore();

        // 2 点咖啡
        Coffee coffee = coffeeStore.orderCoffee("Latte");
        System.out.println(coffee.getName());
    }
}

在Java中,万物皆对象,这些对象都需要创建,如果创建的时候直接new,就会对该对象耦合严重,假如需要更换对象,所有new的地方都需要修改一遍,这显然违背了开闭原则。如果使用工厂来生产对象,就只需要和工厂打交道就好了,彻底和对象解耦,如果需要更换对象,直接在工厂里更换该对象即可,达到了与对象解耦的目的。所以说,工厂模式的最大优点就是:解耦

三种工厂:

  • 简单工厂模式(不属于GOF的23种经典设计模式)
  • 工厂方法模式
  • 抽象工厂模式

简单工厂模式

简单工厂不是一种设计模式,反而比较像是一种编程习惯。

结构

简单工厂包含以下角色:

  • 抽象产品:定义了产品的规范,描述了产品的主要特征和功能(通用行为)
  • 具体产品:实现或继承抽象产品(接口/抽象类)的子类
  • 具体工厂:提供了创建产品的方法,调用者通过该方法来获取产品(根据传递的不同参数来创建不同的产品示例)
实现

image.png
咖啡类:

public abstract class Coffee {

    // 获取咖啡名
    public abstract String getName();

    // 加糖
    public void addSugar(){
        System.out.println("加糖");
    }

    // 加奶
    public void addMilk(){
        System.out.println("加奶");
    }
}

美式咖啡类:

public class AmericanCoffee extends Coffee {
    @Override
    public String getName() {
        return "美式咖啡";
    }
}

拿铁咖啡类:

public class LatteCoffee extends Coffee {
    @Override
    public String getName() {
        return "拿铁咖啡";
    }
}

简单咖啡工厂类:

public class SimpleCoffeeFactory {
    public Coffee createCoffee(String type) {
        // 根据类型创建咖啡实例
        Coffee coffee = null;
        if("Latte".equals(type)) {
            coffee = new LatteCoffee();
        }
        else if("Americano".equals(type)) {
            coffee = new AmericanCoffee();
        }
        else {
            System.out.println("Sorry, we don't have this kind of coffee.");
        }

        return coffee;
    }
}

咖啡店类:

public class CoffeeStore {

    public Coffee orderCoffee(String type) {

        // 实例化工厂
        SimpleCoffeeFactory simpleCoffeeFactory = new SimpleCoffeeFactory();

        // 调用生产咖啡的方法
        Coffee coffee = simpleCoffeeFactory.createCoffee(type);

        // 加糖和奶
        coffee.addSugar();
        coffee.addMilk();

        return coffee;
    }
}

测试:

public class Cilent {
    public static void main(String[] args) {
        // 创建咖啡店类对象
        CoffeeStore coffeeStore = new CoffeeStore();

        // 点咖啡
        Coffee coffee = coffeeStore.orderCoffee("Latte");
        System.out.println(coffee.getName());
    }
}

总结

工厂(factory)处理创建对象的细节,一旦有了SimpleCoffeeFactory,CoffeeStore类中的orderCoffee()就变成此对象的客户,后期如果需要Coffee对象直接从工厂中获取即可。这样就解除了CoffeeStore和Coffee实现类的耦合,同时又产生了新的耦合,CoffeeStore和SimpleCoffeeFactory的耦合,工厂对象和商品对象的耦合。
后期如果需要增加新咖啡,势必需要修改SimpleCoffeeFactory的代码,违反了开闭原则。工厂的客户端可能有很多,如创建美团外卖等,这样只需要修改工厂类的代码,省去了其他的操作。

简单工厂简化了客户端操作,客户端可以调用工厂方法来获取具体的产品,而无需直接与具体产品类交互,降低了耦合,但是有一个很大的问题就是不够灵活,如果需要添加新产品,就需要修改工厂类的代码。

优点:

  • 封装了创建对象的过程,可以通过参数直接获取对象
  • 把对象的创建和业务逻辑层分开,避免了修改客户端的代码,如果要实现新产品直接修改工厂类,不需要在原代码中修改,降低客户代码修改的可能性,更容易扩展

缺点:

  • 增加新产品时需要修改工厂类的代码,违背了开闭原则

扩展(静态工厂)

在实际开发中,一部分开发人员将工厂类中创建对象的功能定义成静态的,这就是静态工厂模式,也不属于23种设计模式,是一种编程习惯。
好处就是客户端可以不用实例化工厂对象,直接调用即可。

public class SimpleCoffeeFactory {
    public static Coffee createCoffee(String type) {
        // 根据类型创建咖啡实例
        Coffee coffee = null;
        if("Latte".equals(type)) {
            coffee = new LatteCoffee();
        }
        else if("Americano".equals(type)) {
            coffee = new AmericanCoffee();
        }
        else {
            System.out.println("Sorry, we don't have this kind of coffee.");
        }

        return coffee;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/471263.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ctf_show笔记篇(web入门---反序列化)

目录 反序列化 254:无用,是让熟悉序列化这个东西的 255:直接使$isViptrue 256:还是使用变量覆盖 257:开始使用魔法函数 258:将序列化最前面的过滤了,使用绕过 259: 这一题需要看writeup才…

用css滤镜做颜色不同的数据卡片(背景图对于css滤镜的使用)

<template> <div class"xx_modal_maincon"><div class"xx_model_bt">履约起始日至计算日配额及履约情况</div><el-row><el-col :span"6"><div class"xx_modal_mod"><div class"mod…

cs推免相关文书模板、基本资料

目录 复试问题 文书模板 机考指南 链接:https://pan.baidu.com/s/1WAAzTPZsASNDt5XRmAO9VA?pwd=21yk 提取码:21yk --来自百度网盘超级会员V5的分享 408专业课复习 链接:https://pan.baidu.com/s/1UI0EwWTy3zn3lm3wTQJ2Dw?pwd=t5gj 提取码:t5gj --来自百度网盘超级会…

【技术栈】Redis 中的事务及持久化方式

SueWakeup 个人主页&#xff1a; SueWakeup 系列专栏&#xff1a;学习技术栈 个性签名&#xff1a;保留赤子之心也许是种幸运吧 本文封面由 凯楠&#x1f4f8; 友情提供 目录 相关传送门 1. Redis 中的事务 2. Redis 持久化 2.1 RDB 方式 2.1.1 RDB手动 2.1.2 RDB自动 2.…

LeetCode:2684. 矩阵中移动的最大次数(DP Java)

目录 2684. 矩阵中移动的最大次数 题目描述&#xff1a; 实现代码与解析&#xff1a; DP 原理思路&#xff1a; 2684. 矩阵中移动的最大次数 题目描述&#xff1a; 给你一个下标从 0 开始、大小为 m x n 的矩阵 grid &#xff0c;矩阵由若干 正 整数组成。 你可以从矩阵第…

C++第八弹---类与对象(五)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】 目录 1、运算符重载 1.1、赋值运算符重载 1.2、前置和后置重载 2、const成员 3、取地址及const取地址操作符重载 总结 1、运算符重载 1.1、赋值运…

MathType注册码永久激活版2024中文版

1、 点击exe的安装包&#xff0c;然后像普通软件一样安装即可&#xff0c;路径选择你可以找到的&#xff08;后面设置会用到&#xff09; 2、安装完成之后&#xff0c;不要打开!不要打开!不要打开!这一步很重要!!!安装之后&#xff0c;打开激活工具&#xff08;激活工具&#x…

Spring之@Autowired注解

Autowired的几种用法 作用在属性上作用在方法上作用在构造器上 demo演示 创建三个普通bean Component public class ComponentA { }Component public class ComponentB { }Component public class ComponentC { } 依赖注入 package com.test.model.component;import org.…

Spring学习记录之依赖注入

问题1&#xff1a; 往一个类中传递数据的方式有哪些呢&#xff0c;其实&#xff0c;只有一种方式&#xff0c;即通过方法&#xff0c;但方法却有多种&#xff0c;一种是我们先前学到的通过set方法&#xff08;普通方法&#xff09;&#xff0c;另一种则是通过构造方法的方式。…

3.19作业

1、思维导图 2、模拟面试题 1&#xff09;TCP通信中的三次握手和四次挥手 答&#xff1a;三次握手 客户端向服务器发送连接请求 服务器向客户端回复应答并向客户端发送连接请求 客户端回复服务端&#xff0c;并建立联系 四次挥手 进程a向进程b发送断开连接请求…

单例设计模式,各种排序复习

1.单例设计模式 资料来源 1.1单例模式是什么&#xff1f; 单例模式&#xff0c;属于创建类型的一种常用的软件设计模式。 通过单例模式的方法创建的类在当前进程中只有一个实例&#xff08;根据需要&#xff0c;也有可能一个线程中属于单例&#xff0c;如&#xff1a;仅线程…

qt Qt Remote Object(QtRO)实现进程间通信

简介 Qt Remote Object简称QtRO&#xff0c;这是Qt5.9以后官方推出来的新模块&#xff0c;专门用于进程间通信&#xff08;IPC&#xff09;。是基于Socket来封装的&#xff0c;兼容LPC和RPC。LPC即Local Process Communication&#xff0c;而RPC是指Remote Process Communicat…

瑞士百达资产管理有限公司拟增三大去中心化数字加密货币支付接口!

简介: 瑞士百达集团成立于1805年,欧洲第三大财富管理公司, 集团拥有约 5,300 名员工,其中包括 900 名投资经理。它在金融服务中心拥有 30 个办事处网络,包括在日内瓦、卢森堡、拿骚、香港和新加坡的注册银行,百达集团管理的资产总额达6380亿瑞士法郎(7670亿美元)。 瑞士百达资…

触手可及的社交:揭示Facebook如何让每个人都能参与其中

引言 在当今社会&#xff0c;Facebook已经成为了人们日常生活中不可或缺的一部分。无论是与朋友、家人保持联系&#xff0c;还是参与社群讨论、获取新闻信息&#xff0c;Facebook都提供了一个触手可及的社交平台。本文将探讨Facebook如何让每个人都能轻松参与其中&#xff0c;…

ClickHouse01-什么是ClickHouse

什么是ClickHouse&#xff1f; 关于发展历史存在的优势与劣势什么是它风靡的原因&#xff1f; 什么是ClickHouse&#xff1f; 官方给出的回答是&#xff0c;它是一个高性能、列式存储、基于SQL、供在线分析处理的数据库管理系统 当然这边不得不提到OLAP(Online Analytical Pr…

代码随想录day24(1)二叉树:最大二叉树(leetcode654)

题目要求&#xff1a; 给定一个不含重复元素的整数数组。一个以此数组构建的最大二叉树定义如下&#xff1a; 二叉树的根是数组中的最大元素。左子树是通过数组中最大值左边部分构造出的最大二叉树。右子树是通过数组中最大值右边部分构造出的最大二叉树。 通过给定的数组构…

【C++】AVL树的两单旋和两双旋

目录 1. 新节点插入较高左子树的左侧---左左&#xff1a;右单旋 代码 2. 新节点插入较高右子树的右侧---右右&#xff1a;左单旋 代码 3. 新节点插入较高左子树的右侧---左右&#xff1a;先左单旋再右单旋 ​编辑 代码 4. 新节点插入较高右子树的左侧---右左&#xff1a;先…

如何选择适合大功率直流电子负载

选择适合大功率直流电子负载时&#xff0c;需要考虑以下几个关键因素&#xff1a; 功率范围&#xff1a;首先&#xff0c;需要确定所需的最大功率范围。大功率直流电子负载通常有不同的功率等级&#xff0c;如1kW、2kW、5kW等。根据实际应用场景和需求&#xff0c;选择合适的功…

CTF题型 php反序列化进阶(1) php原生类 例题和总结

CTF题型 php反序列化进阶(1) php原生文件操作类 例题和总结 文章目录 CTF题型 php反序列化进阶(1) php原生文件操作类 例题和总结特征原理 我们可以通过PHP自身本来就有的类来进行文件操作扫描目录的三个类DirectoryIterator(支持glob://协议)FilesystemIterator&#xff08;继…

基于springboot的stone音乐播放器的设计与实现

摘 要 随着我国经济的高速发展与人们生活水平的日益提高&#xff0c;人们对生活质量的追求也多种多样。尤其在人们生活节奏不断加快的当下&#xff0c;人们更趋向于足不出户解决生活上的问题&#xff0c;stone音乐播放器展现了其蓬勃生命力和广阔的前景。与此同时&#xff0c;…