外观模式详解:轻松搞定复杂子系统

news2024/10/7 12:29:22

childrenday

一、概述

外观模式(Facade Pattern)是一种结构型设计模式,它为多个子系统中的操作提供一个统一的高层接口,用于访问复杂子系统的功能。其核心思想是通过一个外观类将子系统的复杂操作进行封装,客户端只需与外观类进行交互,无需了解子系统的具体操作细节。这大大简化了客户端的使用,同时降低了客户端和子系统的耦合度。

通俗的讲,我们要实现一个功能,可能需要调用一个子系统中的多个操作,或者组合不同子系统中的操作。而外观模式就是提供一个门面,即在一堆子系统之上,提供一个统一的外界访问平台,通过该平台可以一键完成复杂的子系统功能。

今天是六一儿童节,一起致童真,我们用游乐园举个例子。一个大型儿童游乐园,会有很多的收费项目,我们可以在每个项目游玩地单独购票游玩,也可以在游乐场大门口的综合售票平台或者网上平台直接购买所有项目门票,甚至购买通玩票,这大大缩短了排队等待的时间。这就是外观模式的应用,各个项目的售票处代表各个子系统,综合售票平台就是我们的外观,它提供统一的方式访问各个子售票系统。

facade02

外观模式涉及的角色

  • 外观角色(Facade ):一个单独的对象,内部持有子系统的引用,其中定义了一系列方法以访问子系统中的功能。
  • 子系统角色(SubSystem):一组相互关联的类或对象,每个子系统可以独立运作。
  • 客户端(Client):直接与外观对象进行交互,从而间接访问子系统功能。

实现原理

  1. 客户端通过实例化外观对象来访问子系统。
  2. 外观对象内部持有子系统的实例引用。
  3. 外观对象将客户端的请求委派给子系统的相应组件。
  4. 子系统的组件处理具体的工作,并将结果返回给外观对象。
  5. 外观对象将结果返回给客户端。

优点

  • 隐藏子系统的复杂性和具体细节,简化客户端使用:外观模式让客户端通过一个简单的接口与复杂子系统进行交互,无需关注子系统的具体实现,降低了客户端使用难度。
  • 降低客户端和子系统之间的耦合:客户端不直接和子系统交互,使得子系统的变更不会对客户端造成太大影响,是“迪米特法则“的体现。
  • 易于维护:将子系统的操作封装在一个外观类中,使维护和修改变得更容易。

缺点

  • 不符合开闭原则:增加新的子系统可能需要修改外观类或客户端代码。
  • 可能导致功能未被充分利用:统一的高层接口可能会限制子系统的功能使用。
  • 可能造成滥用:将过多的功能放在外观对象中,可能导致外观对象变得庞大和复杂。

适用场景

  • 当你需要为多个复杂子系统提供一个统一的操作接口或简单入口时,可以使用外观模式。
  • 当希望将系统的复杂性隐藏起来,只向客户端暴露必要的接口时,可以使用外观模式。
  • 当客户端与多个子系统之间存在很多依赖关系,希望降低耦合度,可以使用外观模式。

二、案例实现

案例分析

如上图案例所示,我们有三个儿童游乐项目积木乐园、碰碰车和旋转木马,分别代表三个子系统,首先我们可以定义一个抽象接口ChildrenPlayItem,表示所有游乐项目的公共接口,里面定义了购票和游玩的公共行为,然后三个子系统分别实现这个接口完成子系统的功能。接下来定义一个外观类PlayEntry,表示游玩入口,我们要玩什么项目,都从这个入口进入。不管选择几个项目,都可以通过这个入口进行购票和游玩,最后还可以计算所有花费的票价总额。

代码实现

步骤1:创建游乐园项目抽象接口ChildrenPlayItem,里面声明购票和游玩的方法。

public interface ChildrenPlayItem {
    int ticket();
    void play();
}

步骤2:分别实现三个子系统:积木乐园、碰碰车、旋转木马

public class BlockPark implements ChildrenPlayItem {
    private int price=12;
    @Override
    public int ticket() {
        System.out.println("购买积木乐园项目票,票价"+price);
        return price;
    }

    @Override
    public void play() {
        System.out.println("堆积木咯...");
    }
}
public class BumperCar implements ChildrenPlayItem {
    private int price=88;
    @Override
    public int ticket() {
        System.out.println("购买碰碰车项目票,票价"+price);
        return price;
    }

    @Override
    public void play() {
        System.out.println("玩碰碰车咯...");
    }
}
public class Carousel implements ChildrenPlayItem {
    private int price=39;
    @Override
    public int ticket() {
        System.out.println("购买旋转木马项目票,票价"+price);
        return price;
    }

    @Override
    public void play() {
        System.out.println("玩旋转木马咯...");
    }
}

步骤3:创建外观类PlayEntry作为游玩入口

public class PlayEntry {

    private ChildrenPlayItem blockPark; //积木乐园
    private ChildrenPlayItem bumperCar; //碰碰车
    private ChildrenPlayItem carousel; //旋转木马

    private int charge;

    public PlayEntry() {
        this.blockPark = new BlockPark();
        this.bumperCar = new BumperCar();
        this.carousel = new Carousel();
        this.charge=0;
    }
    //玩积木
    public void playBlockPark(){
        int itemPrice=blockPark.ticket();
        blockPark.play();
        charge+=itemPrice;
    }
    //玩碰碰车
    public void playBumperCar(){
        int itemPrice=bumperCar.ticket();
        bumperCar.play();
        charge+=itemPrice;
    }
    //玩旋转木马
    public void playCarousel(){
        int itemPrice=carousel.ticket();
        carousel.play();
        charge+=itemPrice;
    }
    //计费
    public void pay(){
        System.out.println("一共要支付的项目票价总额为:"+charge);
    }
    
}

步骤4:客户端,调用外观类中声明的方法,分别进行三个项目的游玩体验

public class Client {
    public static void main(String[] args) {
        PlayEntry entry=new PlayEntry();
        entry.playBlockPark();
        entry.playBumperCar();
        entry.playCarousel();
        entry.pay();
    }
}

测试结果

image-20230601021542579

三、总结

外观模式为复杂子系统提供了一个简化的接口,让客户端更轻松地操控子系统,同时降低了客户端与子系统之间的耦合度。外观模式也有一些缺点,比如不符合开闭原则,可能导致功能未被充分利用。当然,在合适的场景下,这些缺点就是仁者见仁智者见智了。希望大家在平常的软件开发过程中从能源码中多多发现和学习,这样才可以真正学会设计模式的精髓。

感谢大家阅读这篇关于外观模式讲解的文章,设计模式之美专栏文章目前已经更新了一半,如果大家正在学习设计模式,可以订阅我的专栏,我尽量用最经典的案例、最简洁的代码帮助大家更好地理解和掌握设计模式。如果专栏文章有所疏漏或者不当之处,非常欢迎大家留言指正,希望大家共同进步。
1711edbd2bd444b1b647e09c2c3aff0d

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

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

相关文章

微信朋友圈如何批量发圈

做营销最重要的任务是什么? 毋庸置疑,就是发布朋友圈。 为什么要发圈呢? 发朋友圈是一种推广产品和服务的营销手段。 在如今社交媒体普及的时代,人们大多数时间都在线上,而朋友圈作为微信中的社交场景之一&#xff…

小程序开发,帮助小个体实现品牌化

在这个互联网时代,小程序成为了各大平台的必备。微信作为一款国民级的应用,如今已经拥有近10亿的用户,而小程序作为微信新推出的一款产品,已经被大家熟知。除了微信平台之外,小程序也被很多商家所青睐。因为小程序能带…

C++中《stack和queue的使用》

本文主要讲解栈和队列的常见接口的使用 文章目录 一、栈的介绍和使用1.1 stack的介绍1.2 stack的使用 二、queue的介绍和使用2.1 queue的介绍2.2 queue的使用 一、栈的介绍和使用 1.1 stack的介绍 1️⃣stack是一种容器适配器,专门用在具有后进先出操作的上下文环…

CS5366电路原理图|CS5366demobord参考电路|单芯片PD集成4K60Hz拓展坞芯片设计

ASL CS5366是Type-C转HDMI 4K60HZPDUSB3.0单芯片集成芯片,芯片方案带DSC压缩功能且最高可支持支持RGB 4:4:4 。 CS5366参数特性: 支持最高分辨率/定时4k60Hz 支持DSC v1.2a,并与前一版本向后兼容 支持DSC解码器和直通模式 嵌入式32位RISC-V…

2023年天府杯全国大学生数学建模竞赛B题中国环境问题的治理解题全过程

2023年天府杯全国大学生数学建模竞赛 B题 中国环境问题的治理 原题再现: 问题背景:   随着经济的快速发展和人口的持续增长,中国的环境问题已经成为了一个急需解决的重要问题。这些环境问题不仅对人们的健康和生活质量产生了巨大的影响&a…

笔试强训7

作者:爱塔居 专栏:笔试强训 作者简介:大三学生,希望和大家一起进步 目录 day9 day10 day9 一. 单选 1.下面程序的输出是:() String x"fmn"; x.toUpperCase(); String yx.replace(f,F); yy"wxy"; System.out…

Redis的内存策略(未完成)

过期Key处理: 1)Redis之所以性能强大,最主要的原因就是基于内存来存储,然而单节点的Redis内存不宜设置的过大,否则会影响持久化或者是主从复制的性能,可以通过修改配置文件来设置redis的最大内存,通过maxmemory 1gb&am…

为什么数字化转型就应该选择低代码?一文详解

数字化转型在这几年被反复提及,我们听得耳朵都快起茧子了。数字化在当前经济社会发展中扮演着越来越重要的角色,可以帮助企业更好地理解消费者和市场需求,更好地应对市场竞争,同时也可以提高企业效率,促进经济发展。 究…

WICC · 出海嘉年华倒计时!精彩不容错过,「指南」一手掌握

6.2 广州 WICC出海嘉年华 精彩不容错过 指南一手掌握 -高端峰会 圆桌会议- 超 有 料 话题剧透 如何在巨头林立的热门赛道成功突围? 如何在迅猛发展的新兴市场深挖价值? 如何在复杂合规政策下实现应用增长? 如何利用好底层技术优化本地化…

pip安装库提示Read timed out更换下载源

在使用pip install xx安装库的时候提示 Read timed out. 一般解决方案就两种: 1.延长timeout时间,治标不治本,谁知道到底该延长多少时间才能百分百每次安装都成功。 使用方式: pip --default-timeout1000 install 需要安装的库…

强化学习笔记-07 n-step Bootstrapping 多步TD时分学习

本文是博主对《Reinforcement Learning- An introduction》的阅读笔记,不涉及内容的翻译,主要为个人的理解和思考。 上一节介绍了TD算法,其采用了Bootstrapping方法,当前过去的预估以及即期收益来更新累积收益函数: 前…

通过期待已久的帕丽斯·希尔顿人物化身系列,成为元宇宙的偶像

5,555 个以帕丽斯希尔顿为主题的独特人物化身将于 5 月 31 日推出,每个人物化身均可在 The Sandbox 中使用。 我们与帕丽斯希尔顿及全球流行文化中心的下一代娱乐公司 11:11 Media 合作,很高兴宣布帕丽斯希尔顿的人物化身系列即将推出! 作为对…

Word导出PDF时图片质量下降问题的解决方法

Word导出PDF时图片质量下降问题的解决方法 ⭐️ 最近,在使用Word写完论文以后,另存为“PDF”文件时,发现文档中的图像质量明显下降。本文介绍的方法可以将Word保存为图片无压缩的带有标签的高质量PDF文件,建议仅在定稿时进行以下…

2023系统分析师下午案例分析真题

真题1 阅读以下关于软件系统分析与建模的叙述,在纸上回答问题1至3. 说明: 某软件公司拟开发一套汽车租赁系统,科学安全和方便的管理租赁公司的各项业务,提高公司效率,提升利率。注册用户在使用系统镜像车辆预约时需执行以下操作: (a) 用户登录系统 (b) 查询车辆信息 (c) …

业务安全情报第16期 | 大促8成优惠券竟被“羊毛党”抢走!?

目录 八成秒杀账户是羊毛党 羊毛党风险分析 安全防护及产品组合建议 近期,某电商小程序举办美食节营销活动,提供高额折扣券,并允许用户进行秒杀。然而,羊毛党团伙利用作弊手段,抢购囤券,然后倒卖变现&am…

释放 AI 的力量|2023 年 8 款最佳 AI 图像生成器

1973 年,Harold Cohen 设计的 AARON 系统创造了第一件人工智能生成的艺术品。黑白涂鸦远非所谓的美术,但它们为 DALLE-2 和 Midjourney 等一些出色的 AI 图像生成器奠定了基础。 在过去的 50 年里,AI 图像生成器变得更加智能。通过分析和学习…

线程的概念

文章目录 1. Linux线程概念1.1 什么是线程 2. 页表3. 线程的优点4. 线程的缺点5. 线程用途6.进程和线程7. 线程异常 1. Linux线程概念 1.1 什么是线程 线程是CPU调度的基本单位,它是在进程内部运行的执行流,线程比进程粒度更细,调度成本更低…

(2022,实体迁移)GAN 的通用 one-shot 域自适应

Generalized One-shot Domain Adaptation of Generative Adversarial Networks 公众号:EDPJ 目录 0. 摘要 1. 简介 2. 相关工作 3. 基础 4. 方法 4.1 总览 4.2 风格固定与范例重建 4.3 内部分布学习(Internal distribution learning&#xff0…

计算机硬件(1)

1.4 计算机硬件 电脑硬件是计算机系统中最基本的部分,可理解成看得见、摸得着的实物。一台电脑是由许多的零部件组成,只有这些零部件组合在一起协调工作,才能称之为电脑。一般计算机的硬件可以简单分为以下部件: 主机&#xff08…

sql比赛复习

systemctl start mysqld create database if not exit; 导入数据 编码、分割符号 alter更 http://172.19.100.21:9000/#!/auth 导入数据 简单插叙 创建视图 disti