Java 设计模式---外观模式

外观模式(Facade Pattern)通过提供一个统一的接口,简化了客户端与复杂子系统间的交互。它定义了一个高层次的接口,使得子系统更易于使用,降低了系统各部分的耦合度。在实际应用中,如数据库访问和智能家电控制,外观模式能有效减少代码复杂性,提高可维护性。然而,设计不当可能导致修改外观类,违反开闭原则。
摘要由CSDN通过智能技术生成

目录

一、外观模式

1、外观模式简介

2、外观模式原理

3、外观模式总结


一、外观模式

1、外观模式简介

    外观模式( Facade Pattern),也叫门面模式,外观模式的原始定义是:为子系统中的一组接口提供统一的接口。它定义了一个更高级别的接口,使子系统更易于使用。
    外观模式,是一种通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易被访问的模式。该模式对外有一个统一接口,外部应用程序不用关心内部子系统的具体的细节,这样会大大降低应用程序的复杂度,提高了程序的可维护性。
    门面模式有点类似之前讲到的迪米特法则(最少知识原则)和接口隔离原则:两个有交互的系统,只暴露有限的必要的接口。

    门面模式(facade)又称外观模式。定义:为子系统中的一组接口提供一个一致的界面, Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。定义中提到的子系统是指在设计中为了降低复杂性根据一定的规则(比如业务、功能), 对系统进行的划分。

    门面类充当了系统中的"服务员",它为多个业务类的调用提供了一个统一的入口,简化了类与类之间的交互,如果没有门面类,每个客户类需要和多个子系统之间进行复杂的交互,系统的耦合度将会很大。

2、外观模式原理

外观(Facade)模式包含以下主要角色:
    1、外观(Facade)角色:为多个子系统对外提供一个共同的接口
        外观角色中可以知道多个相关的子系统中的功能和责任。在正常情况下,它将所有从客户端发来的请求委派到相应的子系统,传递给相应的子系统对象处理
    2、子系统(Sub System)角色:实现系统的部分功能,客户可以通过外观角色访问它
        每一个子系统可以是一个类也可以是多个类的集合。每一个子系统都可以被客户端直接调用,或者被外观角色调用。子系统并不知道外观的存在,对于子系统而言,外观角色仅仅是另一个客户端而已。

    3、客户角色:调用facade角色来完成要得到的功能。

代码示例

public class SubSystemA {

    public void methodA(){
        //业务代码
    }
}

public class SubSystemB {

    public void methodB(){
        //业务代码
    }
}

public class SubSystemC {

    public void methodC(){
        //业务代码
    }
}

public class Facade {

    private SubSystemA obj1 = new SubSystemA();
    private SubSystemB obj2 = new SubSystemB();
    private SubSystemC obj3 = new SubSystemC();

    public void method(){
        obj1.methodA();
        obj2.methodB();
        obj3.methodC();
    }
}

public class Client {

    public static void main(String[] args) {

        Facade facade = new Facade();
        facade.method();
    }
}

应用举例:

    1、Facade 模式的一个典型应用就是进行数据库连接。一般我们在每一次对数据库进行访问,都要进行以下操作:先得到 connect 实例,然后打开 connect 获得连接,得到一个statement,执行sql 语句进行查询,得到查询结果集。

    我们可以将这些步骤提取出来,封装在一个类里面。这样,每次执行数据库访问只需要将必要的参数传递到这个类中就可以了。

    2、智能家电控制

    通过智能音箱来控制室内的 灯、电视、空调。本来每个设备都需要进行独立的开关操作,现在通过智能音箱完成对这几个设备的统一控制。 

代码示例

public class Light {

    public void on(){
        System.out.println("打开灯......");
    }

    public void off(){
        System.out.println("关闭灯......");
    }
}

public class TV {

    public void on(){
        System.out.println("打开电视......");
    }

    public void off(){
        System.out.println("关闭电视......");
    }
}

public class AirCondition {

    public void on(){
        System.out.println("打开空调......");
    }

    public void off(){
        System.out.println("关闭空调......");
    }
}

public class SmartAppliancesFacade {

    private Light light;

    private TV tv;

    private AirCondition airCondition;

    public SmartAppliancesFacade() {
        this.light =new Light();
        this.tv = new TV();
        this.airCondition = new AirCondition();
    }

    public void say(String message){
        if(message.contains("打开")){
            on();
        }else if(message.contains("关闭")){
            off();
        }else{
            System.out.println("对不起没有听清楚您说什么! 请重新再说一遍");
        }

    }

    //起床后 语音开启 电灯 电视 空调
    private void on() {
        System.out.println("起床了!");
        light.on();
        tv.on();
        airCondition.on();
    }

    //睡觉前 语音关闭 电灯 电视 空调
    private void off() {
        System.out.println("睡觉了!");
        light.off();
        tv.off();
        airCondition.off();
    }
}

public class Client {

    public static void main(String[] args) {
        //创建外观对象
        SmartAppliancesFacade facade = new SmartAppliancesFacade();

        facade.say("打开家电");
        facade.say("关闭家电");
    }
}

3、外观模式总结

外观模式的优点:
    1、它对客户端屏蔽了子系统组件,减少了客户端所需要处理的对象数目,并使子系统使用起来更加的容易.通过引入外观模式,客户端代码将变得很简单,与之关联的对象也很少.
    2、它实现了子系统与客户端之间的松耦合关系,这使得子系统的变化不会影响到调用它的客户端,只需要调整外观类即可
    3、一个子系统的修改对其他子系统没有任何影响,而子系统内部变化也不会影响到外观对象。
外观模式缺点:
    1、不能很好的控制客户端直接使用子系统类,如果客户端访问子系统类做太多的限制则减少了可变性和灵活性.
    2、如果设计不当,增加新的子系统可能需要修改外观类的源代码,违背了开闭原则.
使用场景分析:

  • 简化复杂系统。 比如,当我们开发了一整套的电商系统后(包括订单、商品、支付、会员等系统),我们不能让用户依次使用这些系统后才能完成商品的购买,而是需要一个门户网站或手机 App 这样简化过的门面系统来提供在线的购物功能
  • 减少客户端处理的系统数量。 比如,在 Web 应用中,系统与系统之间的调用可能需要处理 Database 数据库、Model 业务对象等,其中使用 Database 对象就需要处理打开数据库、关闭连接等操作,然后转换为 Model 业务对象,实在是太麻烦了。如果能够创建一个数据库使用的门面(其实就是常说的 DAO 层),那么实现以上过程将变得容易很多。
  • 让一个系统(或对象)为多个系统(或对象)工作。 比如,线程池 ThreadPool 就是一个门面模式,它为系统提供了统一的线程对象的创建、销毁、使用等。
  • 联合更多的系统来扩展原有系统。 当我们的电商系统中需要一些新功能时,比如,人脸识别,我们可以不需要自行研发,而是购买别家公司的系统来提供服务,这时通过门面系统就能方便快速地进行扩展。
  • 作为一个简洁的中间层。 门面模式还可以用来隐藏或者封装系统中的分层结构,同时作为一个简化的中间层来使用。比如:在秒杀、库存、钱包等场景中,我们需要共享有状态的数据时(如商品库存、账户里的钱),在不改变原有系统的前提下,通过一个中间的共享层(如将秒杀活动的商品库存总数统一放在 Redis 里),就能统一进行各种服务(如:秒杀详情页、商品详情页、购物车等)的调用。

Java 设计模式

有道无术,术尚可求也,有术无道,止于术。
一个程序员最重要的能力是:写出高质量的代码!!
无论你是年轻还是年长,所有程序员都需要记住:时刻努力学习新技术,否则就会被时代抛弃!

1. Composite Pattern:将对象组合成树形结构来表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。常用于处理树形结构的问题。 2. Decorator Pattern:动态地给对象添加一些额外的职责。可以通过包装一个装饰类来实现对原有类的功能扩展,而不需要修改原有类的代码。常用于需要在运行时动态地添加或删除对象的功能。 3. Strategy Pattern:定义一系列算法,将它们一个个封装起来,并且使它们可以相互替换。使得算法可以独立于使用它的客户端而变化。常用于需要在运行时动态地选择算法的情况。 4. Template Pattern:定义一个操作的算法的骨架,而将一些步骤延迟到子类。使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤。常用于算法的框架已经确定,但某些步骤需要由子类来实现的情况。 5. Factory Pattern:定义一个用于创建对象的接口,让子类决定实例化哪一个类。使得一个类的实例化延迟到其子类。常用于需要根据不同的条件创建不同的对象的情况。 6. Observer Pattern:定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。常用于需要实现对象之间的消息传递或者事件触发机制的情况。 7. Builder Pattern:将一个复杂对象的构造过程分解为多个简单的对象构造过程,使得同样的构造过程可以创建不同的表示。常用于需要创建复杂对象的情况。 8. Facade Pattern:为子系统的一组接口提供一个统一的接口,使得子系统更加容易使用。常用于需要简化复杂系统使用的情况。 9. Adapter Pattern:将一个类的接口转换成客户端希望的另一个接口,使得原本由于接口不兼容而不能一起工作的类可以在一起工作。常用于需要将旧接口转换成新接口的情况。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杀神lwz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值