致敬六一,用外观模式实现一个儿童乐园畅玩平台

news2024/11/26 8:47:45

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/595974.html

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

相关文章

IO 多路复用是什么意思?Redis中的IO又是什么?

点击上方关注 “终端研发部” 设为“星标”,和你一起掌握更多数据库知识 本文首发于我的知乎:https://zhuanlan.zhihu.com/p/632776455 当你打开电脑,任何时候都在进行着IO的操作! 比如一次 API 接口调用、向磁盘写入日志信息&…

[数据结构习题]栈——中心对称链

[数据结构习题]栈——中心对称链 👉知识点导航💎:【数据结构】栈和队列 👉[王道数据结构]习题导航💎: p a g e 70.4 page70.4 page70.4 本节为栈和链表综合练习题 题目描述: 🎇思路…

Semaphore线程信号量

文章目录 前言一、Semaphore 是什么?定义对比 二、使用步骤1. 场景分析2. 编码如下 总结 前言 Semaphore 也是juc中的一个关键类,他与之前的lock 类似,也有公平和非公平两种,它与他们应用含义,引用场景有很大的不同; 与阻塞队列类似,但是也不一样;听我细细道来~ 一…

MTK capture 拍照流程

和你一起终身学习,这里是程序员Android 经典好文推荐,通过阅读本文,您将收获以下知识点: 一、多帧拍照请求概览二、多帧拍照回帧概览 一、多帧拍照请求概览 多帧拍照请求概览如下: 多帧拍照请求 1.1 APP 下发拍照请求到 Camera Fr…

新Linux服务器安装Java环境[JDK、Tomcat、MySQL、Nacos、Redis、Nginx]

文章目录 JDK服务Tomcat服务MySQL服务Nacos服务Redis服务Nginx服务 说明:本文不使用宝塔安装 温馨提示宝塔安装命令:yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh JDK服务…

vitepress从0到1,让每个前后端小伙伴都拥有一个属于自己的博客

📸前言 之前周一的个人博客是用vuepress来搭建,但随着文章的数量越来越多,导致每回在启动的时候构建都特别慢,于是周一有了改构建工具的想法。这不,vitepress工具自发布后,在技术圈内一直有些火热&#xf…

数据库新闻速递 亚马逊Cosmos DB 添加了AI toolchain (译)

开头还是介绍一下群,如果感兴趣polardb ,mongodb ,mysql ,postgresql ,redis 等有问题,有需求都可以加群群内有各大数据库行业大咖,CTO,可以解决你的问题。加群请联系 liuaustin3 ,在新加的朋友会分到2群(共…

chatgpt赋能python:如何将Python代码打包成软件

如何将Python代码打包成软件 Python是一种直译式、交互式、面向对象的高级编程语言。由于其简洁明了的语法,Python在科学计算、Web开发、人工智能等领域得到了广泛的应用。但是,Python程序通常需要运行在特定的环境中,这限制了Python程序的移…

NodeJs之同源限制问题

1. 说明 app1是基于3001端口的服务器, app2是基于3002端口的服务器。 gitee地址:https://gitee.com/studyCodingEx/studys/ 2. app1 2.0 app1.js const express require(express); const path require(path); // 向其他服务器端请求数据的模块 const request …

Linux常用命令——gunzip命令

在线Linux命令查询工具 gunzip 用来解压缩文件 补充说明 gunzip命令用来解压缩文件。gunzip是个使用广泛的解压缩程序,它用于解开被gzip压缩过的文件,这些压缩文件预设最后的扩展名为.gz。事实上gunzip就是gzip的硬连接,因此不论是压缩或…

NodeJs之模板引擎及综合案例

0. 数据源 ./views/addtional.art {{ if age > 18 }}age > 18; {{ else if age < 15 }}age < 15; {{ else }}age!!!!!!!! {{/if}}<% if(age > 18){ %> 年龄大于18岁 <% } else if(age < 15) { %> 年龄小于15岁 <% } else { %> 其他年龄段…

Linux驱动开发(I2C系统的重要结构体)

文章目录 前言一、I2C硬件框架二、i2c_adapter三、i2c_client四、i2c_msg总结 前言 本篇文章来讲解I2C系统的重要结构体&#xff0c;了解这些结构体对于编写I2C驱动来说是至关重要的&#xff0c;所以要想编写好一个I2C驱动程序那么就必须先了解这些结构体。 一、I2C硬件框架 …

图片识别工具Tesseract与使用

Tesseract工具是一个图片识别工具&#xff0c; 由HP实验室开发 由Google维护的开源的光学字符识别&#xff08;OCR&#xff09;引擎。它可以直接使用&#xff0c;或者&#xff08;对于程序员&#xff09;使用 API​​ 从图像中提取输入&#xff0c;包括手写的或打印的文本。与M…

KCC@上海正式成立啦!

5月28号下午&#xff0c;开源社区的朋友共聚于上海的一间茶室中&#xff0c;组织召开了 KCC上海第一次线下见面会&#xff0c;并正式成立了 KCC上海。 KCC&#xff08;KAIYUANSHE City Community&#xff09;是由开源社理事兼执行长庄表伟老师号召发起&#xff0c;旨在让开源社…

关于职场中的面试,要是遇到这些问题时,应该怎么回

(点击即可收听) 关于职场中的面试,要是遇到这些问题时,应该怎么回 平常多学一点,面试入职时就少踩一点坑,无论是去面试还是换工作,怎么样去回答面试官,遇到此类的问题,能够应付自如 1. 你觉得这份工作你能胜任? 首先,无论你在面试过程当中表现怎么样,一定要非常坚定,一定可以 …

让身份验证更简单:OAuth2基于令牌方式为第三方应用提供认证和授权方案

随着互联网应用的发展&#xff0c;跨系统身份认证解决方案也在不断演化和改进。下面是它的发展史&#xff1a; 早期的 Web 应用程序使用基于表单的身份验证方式&#xff1b;随着 Web 应用程序数量的增加&#xff0c;需求跨应用程序身份验证的呼声也越来越高&#xff0c;从而出…

行胜于言

点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入&#xff01; 最近在给我女儿辅导作业的过程中&#xff0c;发现了许多小问题&#xff0c;自己偶尔也会因此而焦躁&#xff0c;同时也在反思作为父母应该更好的帮助孩子成长&#xff0c;而AI能力的增强和孩子的成长有什么相似…

【Python】Python系列教程--Python3 VScode(三)

文章目录 前言安装 VS Code 前言 往期回顾&#xff1a; Python系列教程–Python3介绍&#xff08;一&#xff09;Python系列教程–Python3 环境搭建&#xff08;二&#xff09; 准备工作&#xff1a; 安装 VS Code安装 VS Code Python 扩展安装 Python 3 安装 VS Code VS…

Maven仓库(本地仓库+远程仓库)

在 Maven 中&#xff0c;任何一个依赖、插件或者项目构建的输出&#xff0c;都可以称为构件。 Maven 在某个统一的位置存储所有项目的构件&#xff0c;这个统一的位置&#xff0c;我们就称之为仓库。换言之&#xff0c;仓库就是存放依赖和插件的地方。 任何的构件都有唯一的坐标…

VUE代码批量格式化

1、下载安装Visual Studio Code 2、安装插件 Vetur和Format Files 3、配置格式化&#xff0c;点击右下角设置 4、自定义格式化规则 复制下面的配置信息&#xff0c;覆盖原始配置&#xff0c;保存配置。 {"vetur.format.defaultFormatter.html": "js-beauti…