设计模式之外观模式

目录

一.外观模式

二.UML类图

        - 注意事项及细节

三、实例

        3.1. 角色

        3.2. 案例

        3.3.代码演示

                3.3.1未使用设计模式之前

                        效果演示图

                        从上面代码可以看出:

                3.3.2使用设计模式之后

                        效果演示图

                         结论:

                         注意事项及细节

四. 应用

五.总结

                外观模式优点:

                外观模式缺点:


一.外观模式

为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
一个客户类需要和多个业务类交互,由于涉及到的类比较多,导致使用时代码较为复杂。外观模式通过引入一个新的外观类(Facade)来实现该功能,该外观类的实例负责和子系统中类的实例打交道。

二.UML类图

        - 注意事项及细节

 - 装饰者模式一般用于对原有功能进行增强/装饰
  - 动态的将新功能附加到对象上。在对象功能扩展方面,它比继承更有弹性

三、实例

        3.1. 角色

  Client 类
           外观模式的调用者
  ComponentA
           子系统A
              电脑
  ComponentB
              子系统B
              投影仪
  Facade
   HomeTheaterFacade
              家庭影院

        3.2. 案例

                  需求:组装一个家庭影院;

                  电脑打开、投影仪打开、音箱打开、灯光调暗、零食拿出来,电影开始;

                 零食收起来、灯光调亮、音箱关闭、投影仪关闭、电脑关闭,电影结束;

        3.3.代码演示

                3.3.1未使用设计模式之前

package com.chaiyang.demo.demo2;

/**
 * 电脑(故意写两个用不上的功能,依次体现外观模式的优点)
 */
public class ComponentA {
    public void m1(){
        System.out.println("电脑功能一...");
    }
    public void m2(){
        System.out.println("电脑功能二...");
    }

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

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

//投影仪
class ComponentB {
    public void on(){
        System.out.println("投影仪打开...");
    }

    public void off(){
        System.out.println("投影仪关闭...");
    }
}

//音箱
class ComponentC {
    public void on(){
        System.out.println("音箱打开...");
    }

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

//、灯光
class ComponentD {
    public void on(){
        System.out.println("灯光调亮...");
    }

    public void off(){
        System.out.println("灯光调暗...");
    }
}

//零食
class ComponenE {
    public void on(){
        System.out.println("零食拿出来...");
    }

    public void off(){
        System.out.println("零食收起来...");
    }
}
package com.chaiyang.demo.demo2;

public class Client {
    public static void main(String[] args) {
        new ComponentA().on();
        new ComponentB().on();
        new ComponentC().on();
        new ComponentD().off();
        new ComponenE().on();
        System.out.println("电影开始了...");

        System.out.println();
        new ComponenE().off();
        new ComponentD().on();
        new ComponentC().off();
        new ComponentB().off();
        new ComponentA().off();
        System.out.println("电影结束了...");
    }
}

                        效果演示图

 

                        从上面代码可以看出:

客户端调用依赖了所有的子系统(ABCDE),如果该需求**反复**出现,对于客户端调用而言,就不是很方便了;

另一方面,此需求完成只需要依赖各个子系统的其中一部分功能,**其它功能客户端用不上**,依照迪米特法则我们也应该解耦客户端与各个子系统的关系;

                3.3.2使用设计模式之后

package com.chaiyang.demo.demo2;

/**
 * 电脑(故意写两个用不上的功能,依次体现外观模式的优点)
 */
public class ComponentA {
    public void m1(){
        System.out.println("电脑功能一...");
    }
    public void m2(){
        System.out.println("电脑功能二...");
    }

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

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

//投影仪
class ComponentB {
    public void on(){
        System.out.println("投影仪打开...");
    }

    public void off(){
        System.out.println("投影仪关闭...");
    }
}

//音箱
class ComponentC {
    public void on(){
        System.out.println("音箱打开...");
    }

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

//、灯光
class ComponentD {
    public void on(){
        System.out.println("灯光调亮...");
    }

    public void off(){
        System.out.println("灯光调暗...");
    }
}

//零食
class ComponentE {
    public void on(){
        System.out.println("零食拿出来...");
    }

    public void off(){
        System.out.println("零食收起来...");
    }
}
package com.chaiyang.demo.demo2;

public class ComponentFacade {
    ComponentA componentA =new ComponentA();
    ComponentB componentB = new ComponentB();
    ComponentC componentC = new ComponentC();
    ComponentD componentD = new ComponentD();
    ComponentE componenE = new ComponentE();
    public void on(){
        componentA.on();
        componentB.on();
        componentC.on();
        componentD.off();
        componenE.on();
        System.out.println("电影开始了...");
    }

    public void off(){
        componenE.off();
        componentD.on();
        componentC.off();
        componentB.off();
        componentA.off();
        System.out.println("电影结束了...");
    }
}
package com.chaiyang.demo.demo2;

public class Client {
    public static void main(String[] args) {
        ComponentFacade componentFacade = new ComponentFacade();
        componentFacade.on();
        System.out.println();
        componentFacade.off();
    }
}

                        效果演示图

                         结论:

从上面可以看出,客户端只依赖了外观类,彻底解耦了与各个子系统之间的关系

Facade类其实相当于A、B、C模块的外观界面,有了这个Facade类,那么客户端就不需要亲自调用子系统中的A、B、C模块了,也不需要知道系统内部的实现细节,甚至都不需要知道A、B、C模块的存在,客户端只需要跟Facade类交互就好了,从而更好地实现了客户端和子系统中A、B、C模块的解耦,让客户端更容易地使用系统。 

                         注意事项及细节

   - 屏蔽了子系统的细节,因此外观模式降低了客户端对子系统使用的复杂性
  - 对客户端与子系统的耦合关系 - 解耦,让子系统内部的模块更易维护和扩展
  - 当系统需要进行分层设计时,可以考虑使用 Facade 模式

四. 应用

1.  后期代码维护,提取某些类中可用的方法聚合在一起

2.对于一个复杂的子系统,需要为用户提供一个简单的交互操作。
3.客户端程序与多个子系统之间存在很大的依赖性。引入外观类可以将子系统与客户端解耦,从而提高子系统的独立性和可移植性。
4.在层次化结构中,可以使用外观模式定义系统中每一层的入口,层与层之间不直接产生联系,而通过外观类建立联系,降低层之间的耦合度。

五.总结

                外观模式优点:

1. 减少客户端所需处理的对象数目,使得子系统使用起来更加容易。
2.实现了子系统与客户端之间的松耦合关系。
3. 一个子系统的修改对其他子系统没有任何影响,而且子系统内部变化也不会影响到外观对象。

                外观模式缺点:

1. 不能很好地限制客户端直接使用子系统类,如果对客户端访问子系统类做太多的限制则减少了可变性和灵活性。
 2.如果设计不当,增加新的子系统可能需要修改外观类的源代码,违背了开闭原则

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值