自学内容网 自学内容网

对外观模式的理解

一、场景【案例来源

1 题目描述

小明家的电源总开关控制了家里的三个设备:空调、台灯和电视机。每个设备都有独立的开关密码,分别用数字1、2和3表示。即输入1时,空调关闭,输入2时,台灯关闭,输入3时,电视机关闭,当输入为4时,表示要关闭所有设备。请你使用外观模式编写程序来描述电源总开关的操作。

2 输入描述

第一行是一个整数 N(1 <= N <= 100),表示后面有 N 行输入。
接下来的 N 行,每行包含一个数字,表示对应设备的开关操作(1表示关闭空调,2表示关闭台灯,3表示关闭电视机,4表示关闭所有设备)。

3 输出描述

输出关闭所有设备后的状态,当输入的数字不在1-4范围内时,输出Invalid device code.

4 输入示例

4
1
2
3
4

5 输出示例

Air Conditioner is turned off.
Desk Lamp is turned off.
Television is turned off.
All devices are off.

二、如果不采用外观模式

1、实现

  • 客户端:
public class Application {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        for (int i = 0; i < n; i++) {
            int code = scanner.nextInt();
            switch (code) {
                case 1:
                    new AirConditioner().off();
                    break;
                case 2:
                    new DeskLamp().off();
                    break;
                case 3:
                    new Television().off();
                    break;
                case 4:
                    new AllDevice().off();
                    break;
                default: throw new RuntimeException("Invalid code, code must in [1, 4]");
            }
        }
    }
}
  • 子系统1(空调AirConditioner):
public class AirConditioner {
    public void off() {
        System.out.println("Air Conditioner is turned off.");
    }
}
  • 子系统2(台灯DeskLamp)
public class DeskLamp {
    public void off() {
        System.out.println("Desk Lamp is turned off.");
    }
}
  • 子系统3(台灯Television)
public class Television {
    public void off() {
        System.out.println("Television is turned off.");
    }
}
  • 子系统4(所有设备AllDevice)
public class AllDevice {
    public void off() {
        System.out.println("All devices are off.");
    }
}

2、问题

  • 客户端的代码要尽可能抽象,而非具体。否则,当增加一个子系统时,或者关闭设备改为打开设备时,我们不得不修改客户端代码。

三、采用外观模式

  • 外观是一种结构型设计模式, 对各种子系统(可以简单理解为用到的类)进行封装,并提供一个简单 (但有限) 的接口供客户端调用。

1、实现

  • 客户端:
@ComponentScan
public class Application {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Application.class);
        DeviceOffFacade deviceOff = applicationContext.getBean(DeviceOffFacade.class);

        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        for (int i = 0; i < n; i++) {
            int code = scanner.nextInt();
            deviceOff.off(code);
        }
    }
}
  • 外观类:
@Component
public class DeviceOffFacade {
    @Autowired
    private AirConditioner airConditioner;

    @Autowired
    private DeskLamp deskLamp;

    @Autowired
    private Television television;

    @Autowired
    private AllDevice allDevice;

    public void off(int code) {
        switch (code) {
            case 1:
                airConditioner.off();
                break;
            case 2:
                deskLamp.off();
                break;
            case 3:
                television.off();
                break;
            case 4:
                allDevice.off();
                break;
            default: throw new RuntimeException("Invalid code, code must in [1, 4]");
        }
    }
}

2、优点

  • 实际开发中,通过Spring注入各种子系统的bean(如上所示),然后将这些相关bean封装在一个外观类中。可以简化客户端调用各种子系统的代码。
  • 如果当前的DeviceOffFacade不满足需求,例如,新需求:当人回家时,智能门检测到住户的人脸后,先开客厅的灯,然后打开客厅的窗帘等。我们可以定义新的外观类,如DeviceArrangeFacade,提供一个arrange(xxx)方法。

四、个人思考

  • 这应该是我学过的最简单的设计模式了… 思想极其纯粹。在实际开发中,不知不觉就应用过这种设计模式,将屎山代码做一下简单的封装,这样闻起来就没那么臭了:)。

原文地址:https://blog.csdn.net/weixin_37477009/article/details/137798531

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!