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

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

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;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public 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";
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public 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";
    }
    @Override
    public String getName() {
        return name;
    }

    @Override
    public 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();
    }
}

代码结构:

适外观模式之智能家居平台优化版本UML2.drawio

思考:

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

4.定义与组成

外观模式之组成UML

定义:

外观模式(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"));

    }

    @Override
    public 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);
    }
    @Override
    public 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-----------------");
    }

    @Override
    public void addDevice(String deviceName, HomeDevice device) {
        devices.put(deviceName, device);
    }
}
//抽象场景工厂接口
public interface ISceneFactory {
    SmartHomeScene createScene();
}
//离家模式创建工厂
public class AwayHomeISceneFactory implements ISceneFactory {
    @Override
    public 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 + "角度");
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public 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

实现代码结构:

适外观模式之智能家居平台重构版本UML.drawio

总结:

​ 上述代码通过抽象外观接口,通过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.适用场景

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

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

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇