当前位置: 首页 > news >正文

手撕设计模式——智能家居之外观模式

手撕设计模式——智能家居平台之外观模式

1.业务需求

​ 大家好,我是菠菜啊,好久不见,今天给大家带来的是——外观模式。老规矩,在介绍这期内容前,我们先来看看这样的需求:在智能家居平台中,用户怎么样实现场景化操作(如“回家模式”“睡眠模式”)?

请添加图片描述

2.代码实现

Talk is cheap,show me your code.

初版实现思路:

​ 我们直接调用多个子设备,实现回家模式的场景化需求。

初版代码如下:

//家居设备基础接口
public interface HomeDevice {String getName();String getStatus();}
//灯光设备
public class LightDevice implements HomeDevice{private String name;private int brightness=0;public LightDevice(String name){name = name;}public void dim(int level) {brightness = level;System.out.println("灯光调暗至 " + level + "%");}public void onLight(){System.out.println("打开灯光");brightness = 100;}public void offLight(){System.out.println("关闭灯光");brightness = 0;}@Overridepublic String getName() {return name;}@Overridepublic String getStatus() {return "灯光"+ brightness + "%";}
}
//电视设备
public class TVDevice implements HomeDevice{private String name;private String status;public TVDevice(String name){name = name;}public void onTV(){System.out.println("打开TV");status = "on";}public void offTV(){System.out.println("关闭TV");status = "off";}@Overridepublic String getName() {return name;}@Overridepublic String getStatus() {return status;}
}
//空调设备
public class AirCondition implements HomeDevice{private String name;private String status;public AirCondition(String name){name = name;}public void startCooling(){System.out.println("空调制冷");status = "cooling";}public  void off() {System.out.println("空调关机");status = "off";}@Overridepublic String getName() {return name;}@Overridepublic String getStatus() {return status;}
}
//客户端
public class Client {public static void main(String[] args) {LightDevice light = new LightDevice("Light");TVDevice tv = new TVDevice("TV");AirCondition ac = new AirCondition("AC");System.out.println("-----------------HomeModel start-----------------");light.onLight();tv.onTV();ac.startCooling();System.out.println("-----------------HomeModel end-----------------");}
}

执行结果:

请添加图片描述

思考:

​ 上述代码我们也发现一些问题,如客户端(用户)切换到回家模式的时候,需要自行完成三个子设备的调用,用户需要关心这么多细节吗?这样耦合性是不是太强了?于是,我们又经过一系列优化。

3.代码优化

优化代码:

//智能家居外观类
public class SmartHomeFacade {private LightDevice lightDevice;private TVDevice tvDevice;private AirCondition airCondition;public SmartHomeFacade() {lightDevice = new LightDevice("Light");tvDevice = new TVDevice("TV");airCondition = new AirCondition("AirCondition");}public void activeHomeModel() {System.out.println("-----------------activeHomeModel start-----------------");lightDevice.onLight();tvDevice.onTV();airCondition.startCooling();System.out.println("-----------------activeHomeModel end-----------------");System.out.println("deviceName:"+lightDevice.getName()+",status:"+lightDevice.getStatus());System.out.println("deviceName:"+tvDevice.getName()+",status:"+tvDevice.getStatus());System.out.println("deviceName:"+airCondition.getName()+",status:"+airCondition.getStatus());}
}
//客户端
public class Client {public static void main(String[] args) {/*  LightDevice light = new LightDevice("Light");TVDevice tv = new TVDevice("TV");AirCondition ac = new AirCondition("AC");System.out.println("-----------------HomeModel start-----------------");light.onLight();tv.onTV();ac.startCooling();System.out.println("-----------------HomeModel end-----------------");*/SmartHomeFacade smartHomeFacade = new SmartHomeFacade();smartHomeFacade.activeHomeModel();}
}

代码结构:

请添加图片描述

思考:

​ 用户无需要知道所有设备的调用细节,只需简单调用SmartHomeFacade的activeHomeModel方法,实现真正意义上的一键切换回家模式。如果调用逻辑修改或者添加新设备了,客户端无感知,进一步降低耦合,符合迪米特法则

4.定义与组成

请添加图片描述

定义:

外观模式(Facade Pattern)是一种结构型设计模式**,它提供了一个统一的接口,用于访问子系统中的一组接口。外观模式定义了一个高层接口,这个接口使得子系统更容易使用。**

组成:

  • 外观(Facade):提供统一的调用接口,将客户端请求委派给适当的子系统对象
  • 子系统(SubSystem):实现具体功能,被外观类调用

核心思想

封装复杂性,提供简单接口
通过创建一个简化的高层接口,隐藏子系统的实现细节,降低客户端与子系统的耦合度。

5.代码重构(工厂模式+抽象外观模式)

思考:

​ 上述的代码实现依赖外观类,不够抽象,而且新增家居设备需要修改外观类,而且不支持动态扩展场景,所以了解了问题后我们进一步重构了代码。

代码重构:

//抽象智能家居外观接口
public interface ISmartHomeFacade {//切换到回家模式void activeHomeModel();//切换到睡眠模式void activateSleepMode();// 扩展点:动态添加设备void addDevice(String deviceName, HomeDevice device);// 获取设备<T extends HomeDevice> T getDevice(Class<T> deviceClass);
}
//动态智能家居外观类
public class DynamicSmartHomeFacade implements ISmartHomeFacade{private final Map<String, HomeDevice> devices = new HashMap<>();public DynamicSmartHomeFacade() {addDevice("Light",new LightDevice("Light"));addDevice("TV",new TVDevice("TV"));addDevice("AirCondition",new AirCondition("AirCondition"));}@Overridepublic void activeHomeModel() {System.out.println("-----------------activeHomeModel start-----------------");getDevice(LightDevice.class).onLight();getDevice(TVDevice.class).onTV();getDevice(AirCondition.class).startCooling();System.out.println("-----------------activeHomeModel end-----------------");}// 泛型方法获取设备@SuppressWarnings("unchecked")public <T extends HomeDevice> T getDevice(Class<T> deviceClass) {return devices.values().stream().filter(deviceClass::isInstance).map(device -> (T) device).findFirst().orElseThrow(() -> new RuntimeException("Device not found: " + deviceClass.getSimpleName()));}public boolean hasDevice(Class<? extends HomeDevice> deviceClass) {return devices.values().stream().anyMatch(deviceClass::isInstance);}@Overridepublic void activateSleepMode() {System.out.println("-----------------activateSleepMode start-----------------");getDevice(LightDevice.class).dim(10);getDevice(TVDevice.class).offTV();getDevice(AirCondition.class).startCooling();System.out.println("-----------------activateSleepMode end-----------------");}@Overridepublic void addDevice(String deviceName, HomeDevice device) {devices.put(deviceName, device);}
}
//抽象场景工厂接口
public interface ISceneFactory {SmartHomeScene createScene();
}
//离家模式创建工厂
public class AwayHomeISceneFactory implements ISceneFactory {@Overridepublic SmartHomeScene createScene() {return new SmartHomeScene("离家模式",(facade->{System.out.println("-----------------activeAwayHomeModel start-----------------");facade.getDevice(LightDevice.class).offLight();facade.getDevice(TVDevice.class).offTV();facade.getDevice(AirCondition.class).off();System.out.println("-----------------activeAwayHomeModel end-----------------");}));}
}
//场景管理
public class SceneManager {private final Map<String, ISceneFactory> sceneFactories = new HashMap<>();private final ISmartHomeFacade facade;public SceneManager(ISmartHomeFacade facade) {this.facade = facade;}public void registerScene(String name, ISceneFactory factory) {sceneFactories.put(name, factory);}public void activateScene(String name) {ISceneFactory factory = sceneFactories.get(name);if(factory != null) {SmartHomeScene scene = factory.createScene();scene.execute(facade);}}
}
//动态场景类
public class SmartHomeScene {private final String sceneName;private final Consumer<ISmartHomeFacade> sceneExecutor;public SmartHomeScene(String sceneName, Consumer<ISmartHomeFacade> sceneExecutor) {this.sceneName = sceneName;this.sceneExecutor = sceneExecutor;}public void execute(ISmartHomeFacade facade) {sceneExecutor.accept(facade);}
}
//智能床设备
public class SmartBedDevice implements HomeDevice{private String name;private int angle=0;public SmartBedDevice(String name){name = name;}public void adjust(int angle) {angle = angle;System.out.println("智能床调至 " + angle + "角度");}@Overridepublic String getName() {return name;}@Overridepublic String getStatus() {return "智能床"+ angle + "角度";}
}
//客户端
public class Client2 {public static void main(String[] args) {DynamicSmartHomeFacade facade = new DynamicSmartHomeFacade();// 开启回家模式facade.activeHomeModel();// 添加智能床设备facade.addDevice("SmartBed", new SmartBedDevice("SmartBed"));// 开启睡眠模式facade.activateSleepMode();ISceneFactory factory = new AwayHomeISceneFactory();SceneManager sceneManager = new SceneManager(facade);sceneManager.registerScene("离家模式", factory);sceneManager.activateScene("离家模式");}
}

上述代码执行结果:

image-20250729173355604

实现代码结构:

请添加图片描述

总结:

​ 上述代码通过抽象外观接口,通过addDevice()方法添加,无需修改外观类,通过SceneManager动态注册场景工厂新增场景,实现设备热插拔以及场景热部署。这种基于抽象接口的外观模式实现,不仅遵循了开闭原则,还为智能家居系统提供了强大的扩展能力。通过动态设备管理和场景工厂等机制,系统可以在不修改核心代码的情况下持续演进,完美适应快速变化的智能家居生态。

6.应用示例

​ 其实外观模式我们在日常开发的时候应用的很广泛,下面是一些示例:

6.1日志框架

// SLF4J是典型的外观模式实现
Logger logger = LoggerFactory.getLogger(MyClass.class);
logger.info("This is a log message");

6.2 Spring框架

// JdbcTemplate封装了JDBC的复杂性
jdbcTemplate.query("SELECT * FROM users", new BeanPropertyRowMapper<>(User.class));

6.3 Files类

// Files类封装了文件操作的复杂性
Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);

7.适用场景

场景类型是否适用原因
系统复杂且模块多✅ 非常适用简化客户端调用
需要解耦客户端与子系统✅ 推荐使用降低依赖关系
需要为子系统提供统一入口✅ 理想选择提供简洁接口
需要逐步重构遗留系统✅ 适用作为中间层

技术需要沉淀,同样生活也是~
个人链接:博客,欢迎一起交流

http://www.lryc.cn/news/604296.html

相关文章:

  • iOS 签名证书与上架流程详解,无 Mac 环境下的上架流程
  • 专题:2025机器人产业技术图谱与商业化指南|附130+份报告PDF、数据汇总下载
  • 2025光伏自动化破局!艾利特机器人用“智能感知+柔性控制”领跑行业
  • Scala实现常用排序算法
  • USB电源原理图学习笔记
  • 开源 Arkts 鸿蒙应用 开发(十二)传感器的使用
  • STM32 外部中断 和 定时器中断
  • 第六章第一节 TIM 定时中断
  • (RedmiBook)上禁用触摸板或自带键盘
  • mybatis-入门
  • 《Vuejs设计与实现》第 12 章(组件实现原理 下)
  • 量子图灵机 Quantum Turing Machine, QTM
  • 【从基础到实战】STL string 学习笔记(上)
  • 如何在出售Windows11/10/8/7前彻底清除电脑数据
  • Python 使用 asyncio 包处理并 发(使用asyncio包编写服务器)
  • Linux的小程序——进度条
  • 重生之我在10天内卷赢C++ - DAY 1
  • 红绿多空策略
  • 华为昇腾×绿算全闪存缓存释放澎湃潜能
  • 【C++详解】深入解析多态 虚函数、虚函数重写、纯虚函数和抽象类、多态原理、重载/重写/隐藏的对⽐
  • 基于 Hadoop 生态圈的数据仓库实践 —— OLAP 与数据可视化(六)
  • ‌CASE WHEN THEN ELSE END‌
  • 分布式系统:一致性
  • Linux常用基础命令
  • 【大语言模型入门】—— Transformer 如何工作:Transformer 架构的详细探索
  • 【C语言】指针深度剖析(一)
  • LeetCode 11 - 盛最多水的容器
  • VUE进阶案例
  • RabbitMQ 消息持久化的三大支柱 (With Spring Boot)
  • Hyperchain账本数据存储机制详解