设计模式(二、三):创建型之工厂方法和抽象工厂模式

news2024/11/27 12:47:51

设计模式系列文章

设计模式(一):创建型之单例模式

设计模式(二、三):创建型之工厂方法和抽象工厂模式

设计模式(四):创建型之原型模式

设计模式(五):创建型之建造者模式

设计模式(六):结构型之代理模式


目录

  • 一、设计模式分类
  • 二、概述
  • 三、简单工厂模式
    • 1、结构
    • 2、实现
    • 3、扩展:静态工厂
  • 四、工厂方法模式
    • 1、结构
    • 2、 实现
    • 3、优缺点
  • 五、抽象工厂模式
    • 1、结构
    • 2、实现
    • 3、优缺点
  • 六、JDK源码解析-Collection.iterator方法


一、设计模式分类

  • 创建型模式
    • 用于描述“怎样创建对象”,它的主要特点是“将对象的创建与使用分离”
    • 提供了单例、原型、工厂方法、抽象工厂、建造者 5 种创建型模式
  • 结构型模式
    • 用于描述如何将类或对象按某种布局组成更大的结构
    • 提供了代理、适配器、桥接、装饰、外观、享元、组合 7 种结构型模式
  • 行为型模式
    • 用于描述类或对象之间怎样相互协作共同完成单个对象无法单独完成的任务,以及怎样分配职责
    • 提供了模板方法、策略、命令、职责链、状态、观察者、中介者、迭代器、访问者、备忘录、解释器 11 种行为型模式

二、概述

需求:设计一个咖啡店点餐系统

  • 设计一个咖啡类(Coffee)
  • 并定义其两个子类(美式咖啡【AmericanCoffee】和拿铁咖啡【LatteCoffee】)
  • 再设计一个咖啡店类(CoffeeStore),咖啡店具有点咖啡的功能
  • 具体类的设计如下:

在这里插入图片描述

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

三、简单工厂模式

  • 简单工厂不属于23种经典设计模式之一
  • 简单工厂不是一种设计模式,反而比较像是一种编程习惯

1、结构

简单工厂包含如下角色:

  • 抽象产品 :定义了产品的规范,描述了产品的主要特性和功能
  • 具体产品 :实现或者继承抽象产品的子类
  • 具体工厂 :提供了创建产品的方法,调用者通过该方法来获取产品

2、实现

现在使用简单工厂对上面案例进行改进,类图如下:

在这里插入图片描述
工厂类代码如下:

public class SimpleCoffeeFactory {
    public Coffee createCoffee(String type) {
        Coffee coffee = null;
        if("americano".equals(type)) {
            coffee = new AmericanoCoffee();
        } else if("latte".equals(type)) {
            coffee = new LatteCoffee();
        }
        return coffee;
    }
}
  • 如果需要Coffee对象直接从SimpleCoffeeFactory工厂中获取即可
  • 这样也就解除了和Coffee实现类的耦合,同时又产生了新的耦合
    • CoffeeStore对象和SimpleCoffeeFactory工厂对象的耦合
    • 工厂对象和商品对象的耦合
  • 如果再加新品种的咖啡,我们势必要需求修改SimpleCoffeeFactory的代码,违反了开闭原则

3、扩展:静态工厂

  • 在开发中也有一部分人将工厂类中的创建对象的功能定义为静态的
  • 这个就是静态工厂模式,它也不是23种设计模式中的
  • 代码如下:
public class SimpleCoffeeFactory {
    public static Coffee createCoffee(String type) {
        Coffee coffee = null;
        if("americano".equals(type)) {
            coffee = new AmericanoCoffee();
        } else if("latte".equals(type)) {
            coffee = new LatteCoffee();
        }
        return coffe;
    }
}

四、工厂方法模式

  • 针对上例中的缺点,使用工厂方法模式就可以完美的解决,完全遵循开闭原则
  • 定义一个用于创建对象的接口,让子类决定实例化哪个产品类对象
  • 工厂方法使一个产品类的实例化延迟到其工厂的子类

1、结构

工厂方法模式的主要角色:

  • 抽象工厂(Abstract Factory):提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法来创建产品
  • 具体工厂(ConcreteFactory):主要是实现抽象工厂中的抽象方法,完成具体产品的创建
  • 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能
  • 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应

2、 实现

使用工厂方法模式对上例进行改进,类图如下:

在这里插入图片描述

抽象工厂:

public interface CoffeeFactory {
    Coffee createCoffee();
}

具体工厂:

public class LatteCoffeeFactory implements CoffeeFactory {

    public Coffee createCoffee() {
        return new LatteCoffee();
    }
}

public class AmericanCoffeeFactory implements CoffeeFactory {

    public Coffee createCoffee() {
        return new AmericanCoffee();
    }
}

咖啡店类:

public class CoffeeStore {

    private CoffeeFactory factory;

    public CoffeeStore(CoffeeFactory factory) {
        this.factory = factory;
    }

    public Coffee orderCoffee(String type) {
        Coffee coffee = factory.createCoffee();
        coffee.addMilk();
        coffee.addsugar();
        return coffee;
    }
}
  • 要增加产品类时也要相应地增加工厂类,不需要修改工厂类的代码了,这样就解决了简单工厂模式的缺点
  • 工厂方法模式是简单工厂模式的进一步抽象
  • 由于使用了多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点

3、优缺点

优点

  • 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程
  • 在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,满足开闭原则

缺点

  • 每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度

五、抽象工厂模式

  • 工厂方法模式中考虑的是一类产品的生产,如畜牧场只养动物、电视机厂只生产电视机

  • 工厂方法模式只考虑生产同等级的产品,但是在现实生活中许多工厂是综合型的工厂,能生产多等级(种类) 的产品

  • 本节要介绍的抽象工厂模式将考虑多等级产品的生产,将同一个具体工厂所生产的位于不同等级的一组产品称为一个产品族

  • 下图所示横轴是产品等级,也就是同一类产品

  • 纵轴是产品族,也就是同一品牌的产品,同一品牌的产品产自同一个工厂
    在这里插入图片描述

    在这里插入图片描述

  • 抽象工厂模式是工厂方法模式的升级版本

  • 工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品

1、结构

抽象工厂模式的主要角色如下:

  • 抽象工厂(Abstract Factory):提供了创建产品的接口,它包含多个创建产品的方法,可以创建多个不同等级的产品
  • 具体工厂(Concrete Factory):主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建
  • 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品
  • 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间是多对一的关系

2、实现

  • 现咖啡店业务发生改变,不仅要生产咖啡还要生产甜点,如提拉米苏、抹茶慕斯等
  • 要是按照工厂方法模式,需要定义提拉米苏类、抹茶慕斯类、提拉米苏工厂、抹茶慕斯工厂、甜点工厂类,很容易发生类爆炸情况
  • 拿铁咖啡和提拉米苏是同一产品族(也就是都属于意大利风味)
  • 美式咖啡和抹茶慕斯是同一产品族(也就是都属于美式风味)
  • 使用抽象工厂模式实现。类图如下:

在这里插入图片描述

抽象工厂:

public interface DessertFactory {

    //生产咖啡的功能
    Coffee createCoffee();

    //生产甜品的功能
    Dessert createDessert();
}

具体工厂:

//美式甜点工厂
public class AmericanDessertFactory implements DessertFactory {

    public Coffee createCoffee() {
        return new AmericanCoffee();
    }

    public Dessert createDessert() {
        return new MatchaMousse();
    }
}
//意大利风味甜点工厂
public class ItalyDessertFactory implements DessertFactory {

    public Coffee createCoffee() {
        return new LatteCoffee();
    }

    public Dessert createDessert() {
        return new Tiramisu();
    }
}

客户端:

  • Coffee和Dessert是抽象产品类
  • show(),抽象类中定义行为,具体实现交给子类
public class Client {
    public static void main(String[] args) {
        //创建的是意大利风味甜品工厂对象
        //ItalyDessertFactory factory = new ItalyDessertFactory();
        AmericanDessertFactory factory = new AmericanDessertFactory();
        //获取拿铁咖啡和提拉米苏甜品
        Coffee coffee = factory.createCoffee();
        Dessert dessert = factory.createDessert();

        System.out.println(coffee.getName());
        dessert.show();
    }
}

如果要加同一个产品族的话,只需要再加一个对应的工厂类即可,不需要修改其他的类

3、优缺点

优点

  • 当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的工厂对象

缺点

  • 当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改

六、JDK源码解析-Collection.iterator方法

public class Demo {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("令狐冲");
        list.add("风清扬");
        list.add("任我行");

        //获取迭代器对象
        Iterator<String> it = list.iterator();
        //使用迭代器遍历
        while(it.hasNext()) {
            String ele = it.next();
            System.out.println(ele);
        }
    }
}
  • 对上面的代码大家应该很熟,使用迭代器遍历集合,获取集合中的元素
  • 而单列集合获取迭代器的方法就使用到了工厂方法模式
  • 通过类图看看结构

在这里插入图片描述

  • Collection接口是抽象工厂类(声明Iterator iterator()方法)
  • ArrayList是具体的工厂类(new Itr()创建返回Iterator对象)
  • Iterator接口是抽象商品类(Itr实现Iterator接口类)
  • ArrayList类中的Iter内部类是具体的商品(Itr是ArrayList内部类)
  • 在具体的工厂类中iterator()方法创建具体的商品类的对象

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

校园综合能效平台建设的意义

摘 要&#xff1a;为响应国家绿色校园建设的号召&#xff0c;切实提高高校能源利用水平&#xff0c;促进学校能源资源合理配置&#xff0c;服务学校高质量发展大局&#xff0c;根据教育部印发的《关于开展节能减排学校行动的通知》《关于勤俭节约办教育建设节约型校园的通知》…

Linux内核超级装备eBPF技术详细研究

定义一&#xff08;http://ebpf.io的定义&#xff09; eBPF (which is no longer an acronym for anything) is a revolutionary technology with origins in the Linux kernel that can run sandboxed programs in a privileged context such as the operating system kernel.…

物联网通信之串口服务器,RS485/RS232双串口并行、远程虚拟串口调试

随着现代工业信息技术发展&#xff0c;串口服务器在工业应用中越来越常见&#xff0c;那么什么是串口服务器呢&#xff0c;今天智联物联小编就与大家分享一下物联网通信中的串口服务器。 为帮助大家理解&#xff0c;智联物联小编从串口服务器的接口为大家开始讲解&#xff0c;一…

高分子PEG:mPEG-Maleimide MW:3400,甲氧基-聚乙二醇—马来酰亚胺,常用作聚合物试剂

【产品描述】 陕西新研博美生物科技有限公司供应的​mPEG-Maleimide属于高分子PEG&#xff0c;马来酰亚胺和巯基的偶合是蛋白和多肽偶联中的一个非常有用的反应。mPEG-MAL被用来合成具有确定结构和生物活性的PEG-蛋白质偶合物。mPEG-MAL也常用作聚合物试剂来选择性诱捕含巯基的…

易基因:小檗碱通过介导m6A mRNA甲基化调控斑马鱼肝细胞氧化应激、凋亡和自噬|科研进展

大家好&#xff0c;这里是专注表观组学十余年&#xff0c;领跑多组学科研服务的易基因。 中药小檗碱&#xff08;Berberine&#xff0c;BBR&#xff0c;化学式C20H18NO4&#xff09;是从几种药用植物中分离出的一种异喹啉季生物碱&#xff0c;包括小檗&#xff08;Berberis ar…

让你不再好奇怎样同声传译

众所周知&#xff0c;同声传译技术在国际交流和商务领域发挥着重要的作用&#xff0c;它能够帮助人们跨越语言障碍&#xff0c;促进人们之间的有效沟通。那么&#xff0c;你知道如何同声传译吗&#xff1f;接下来我将教你三个方法&#xff0c;帮助你更好的进行同声传译操作。 方…

springboot+vue餐厅点餐系统在线点餐系统(含源码+数据库)

1.系统分析 系统用例图如下所示。 从用户、餐厅等方面进行需求分析如下。 1.用户需求&#xff1a;系统应该提供简单易用的用户界面&#xff0c;用户可以浏览餐厅菜单&#xff0c;选择菜品&#xff0c;下订单。此外&#xff0c;应该允许用户管理个人信息和查看历史订单。 2.餐…

SQL-多表查询-事务

SQL-多表查询-事务 多表查询顾名思义就是从多张表中一次性的查询出我们想要的数据 前期表准备 DROP TABLE IF EXISTS emp; DROP TABLE IF EXISTS dept;# 创建部门表CREATE TABLE dept(did INT PRIMARY KEY AUTO_INCREMENT,dname VARCHAR(20));# 创建员工表CREATE TABLE emp (i…

一文3000字从0到1用Python做安全测试攻击实战(建议收藏)

在本文中&#xff0c;我们将使用Python进行一次安全测试的实战演练&#xff0c;目标是找出并利用应用程序的安全漏洞。请注意&#xff0c;这个演练仅用于教育和研究目的&#xff0c;切勿将这些技术用于非法活动。 注意&#xff1a;未经授权的攻击是违法的。确保你在拥有明确权…

准实时刷新集群中各节点本地缓存的解决方案

目录 背景 Redis发布订阅 MQ广播消息 配置中心Nacos&#xff0c;Zookeeper监听 注册中心获取服务节点ip端口接口调用 本地定时任务兜底 背景 我们在系统开发过程中&#xff0c;为了减少数据库和redis缓存的查询以提升接口性能&#xff0c;有时候会把一些常用的、变动不是…

[数据结构 -- C语言] 堆实现Top-K问题,原来王者荣耀的排名是这样实现的,又涨知识了

目录 1、什么是Top-K问题&#xff1f; 1.1 Top-K基本思路 2、Top-K问题逻辑分析 2.1 建堆&#xff0c;大小为K的小堆 2.2 将剩余的N - K 个元素依次与堆顶元素比较&#xff0c;大于就替换 2.3 打印堆 3、TopK实现代码 4、Top-K问题完整代码 结果展示&#xff1a; TopK…

做IT运维的,哪有人不疯的

网飞最新的剧集《怒呛人生》大受欢迎的一大原因就是&#xff1a;发疯。 在2023年&#xff0c;发疯已经从一种人身攻击&#xff0c;拯救语言匮乏的恶评转移成一个中性词&#xff0c;在某些语境下&#xff0c;等同于冒犯、破罐子破摔。连快乐都不敢的东亚人&#xff0c;为啥发疯…

C++:智能指针

目录 一. 智能指针的概念及原理 1.1 什么是智能指针 1.2 智能指针的原理 二. 智能指针的拷贝问题 三. auto_ptr 3.1 auto_ptr的拷贝构造和赋值问题 3.2 auto_ptr的模拟实现 四. unique_ptr 五. shared_ptr 5.1 shared_ptr的常用接口 5.2 shared_ptr的拷贝构造和赋值…

软件工程导论(四)软件编码测试与维护

一、软件编程 1.1良好的编程习惯 变量命名有意义并且使用统一的命名规则 编写自文档代码&#xff08;序言性注释 or 行内注释&#xff09; 提前进行可维护性考量&#xff08;可以用常量的方式存在的数值最好以变量的方式存在&#xff09; 良好的视觉安排可以提高代码的可读性(…

ChatGPT训练一次要耗多少电?

如果开个玩笑&#xff1a;问ChatGPT最大的贡献是什么&#xff1f; “我觉得它对全球变暖是有一定贡献的。”知名自然语言处理专家、计算机科学家吴军在4月接受某媒体采访时如是说。 随着ChatGPT引爆AIGC&#xff0c;国内外巨头纷纷推出自己的AI大模型&#xff0c;大家为人工智…

2023 开放原子全球开源峰会“开发者之夜”高能剧透!

开发者之夜~即将高燃启动 最潮&#xff01;最嗨&#xff01;最青春&#xff01; 肆意&#xff01;亲切&#xff01;嗨 FUN 派&#xff01; 这是一场面向开发者的线下狂欢&#xff01; 也是一场精心准备的答谢盛宴&#xff01; 更是一场开源圈的老友聚会&#xff01; 开发者之夜…

IP地址中的子网掩码和CIDR

将常规的子网掩码转换为二进制&#xff0c;将发现子网掩格式为连续的二进制1跟连续0&#xff0c;其中子网掩码中为1的部分表示网络ID&#xff0c;子网掩中为0的表示主机ID。比如255.255.0.0转换为二进制为11111111 11111111 00000000 00000000。 ​ 在前面所举的例子中为什么不…

Yakit: 集成化单兵安全能力平台使用教程·Web Fuzzer篇

Yakit: 集成化单兵安全能力平台使用教程Web Fuzzer篇 1.数据包共享2.数据包扫描3.使用Web Fuzzer进行模糊测试4.常用 fuzz 标签5.热加载Fuzz1.数据包共享 分享/导入功能可用于信息分享,分享可以设置有效时长和分享密码,凭分享id和密码可以导入分享者的请求包 注意:数据包是…

uni-app 自定义组件之星级评价分数

效果图&#xff1a; 1.自定义组件starsRating.vue文件&#xff08;放在components文件夹内&#xff09; 代码截图&#xff1a; 对应的代码&#xff1a; <image click“btnStars1” class“starsicon” :src“starsObject[0]” mode“widthFix”> <image click“…

redis基础-----安装及使用场景基础操作

需要使用的网址 Redis中文网 Download | Redis 数据库及缓存架构选型网址&#xff1a; DB-Engines Ranking - popularity ranking of database management systems 常识&#xff1a; 存储方面&#xff1a; 磁盘&#xff1a; 1&#xff0c;寻址&#xff1a;ms 2&#xff…