Fun论设计模式之3:外观模式(Facade Pattern)

  在上一篇文章Fun论设计模式之2:代理模式(Proxy Pattern)中,我们知道了代理模式本质上就是对类的访问过程做同样类型的控制。

  那里有提到,把不同模块的API也放到代理类中,并给这些API做相同的前置处理,就可以减少日后的工作量。这个处理,也涉及到一个设计模式——外观模式。

  搬运runoob的描述:

  意图:为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

  主要解决:降低访问复杂系统的内部子系统时的复杂度,简化客户端与之的接口。

  何时使用: 1、客户端不需要知道系统内部的复杂联系,整个系统只需提供一个"接待员"即可。 2、定义系统的入口。

  如何解决:客户端不与系统耦合,外观类与系统耦合。

  关键代码:在客户端和复杂系统之间再加一层,这一层将调用顺序、依赖关系等处理好。

  外观模式在Java web的Spring系统之中有很大体现。Spring使用maven理清类包依赖关系和调用顺序,还隐藏了相当复杂的依赖注入等过程,开发者只需调用过滤器(拦截器),写好MVC三层结构,没有繁杂的初始化过程。这就是外观模式。

  华为云API调用类这里,也是把代理过程和具体的初始化过程给封装了,外部类只需拿到VPCUtil执行业务,或者被封装的业务函数本身。

  在上一节,我们把虚拟私有云的API类封装了一遍,如果每个业务的API类都要封装,那么执行过程是这样的:  

图1. 用0.2版本TokenProxy代理之后,华为云API模块操作流程图

  实际上还可以再优化一下,把4种业务的API封装到一起,因为这几种业务使用的token是一样的,都是从华为云身份验证服务拿到的(何时使用)。

  为了减少代理类的代码量,我们先声明一个SuperUtil类,然后把这4种业务API类都作为子类继承(关键代码):

1 public abstract class SuperUtil {
2     protected String username;
3     protected String password;
4     protected String token;
5     protected String projectId;
6     protected long overDate;
7 }

业务API父类

  这些属性,业务类就无需再次声明了。

 1 package zhyx_cloud;
 2
 3 import java.lang.reflect.Method;
 4
 5 import org.springframework.cglib.proxy.Enhancer;
 6 import org.springframework.cglib.proxy.MethodInterceptor;
 7 import org.springframework.cglib.proxy.MethodProxy;
 8
 9 public class TokenProxy {
10
11     private VPCUtil VPCProxy = null;
12
13     private ECSUtil ECSProxy = null;
14
15     private SecurityGroupUtil SecurityGroupProxy = null;
16
17     private PublicIPUtil PublicIPProxy = null;
18
19     private MethodInterceptor interceptorFactory(String username, String password){
20         return new MethodInterceptor() {
21             @Override
22             public Object intercept(Object sub, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
23                 SuperUtil superUtil = (SuperUtil)sub;
24                 if(superUtil.token == null || System.currentTimeMillis() > superUtil.overDate) {
25                     TokenAndProject tap = new IAMUtil().getToken(username,password);
26                     VPCUtil myproxy = (VPCUtil)sub;
27                     myproxy.token = tap.getToken();
28                     myproxy.projectId = tap.getProjectId();
29                     myproxy.overDate = System.currentTimeMillis() + 23*60*60*1000;
30                 }
31                 Object res = methodProxy.invokeSuper(sub, objects);
32                 return res;
33             }
34         };
35     }
36
37     public TokenProxy(String username, String password) {
38         Enhancer enhancer = new Enhancer();
39         enhancer.setSuperclass(VPCUtil.class);
40         enhancer.setCallback(this.interceptorFactory(username, password));
41         this.VPCProxy= (VPCUtil)enhancer.create();
42         enhancer = new Enhancer();
43         enhancer.setSuperclass(ECSUtil.class);
44         enhancer.setCallback(this.interceptorFactory(username, password));
45         this.ECSProxy = (ECSUtil)enhancer.create();
46         enhancer = new Enhancer();
47         enhancer.setSuperclass(SecurityGroupUtil.class);
48         enhancer.setCallback(this.interceptorFactory(username, password));
49         this.SecurityGroupProxy = (SecurityGroupUtil)enhancer.create();
50         enhancer = new Enhancer();
51         enhancer.setSuperclass(PublicIPUtil.class);
52         enhancer.setCallback(this.interceptorFactory(username, password));
53         this.PublicIPProxy = (PublicIPUtil)enhancer.create();
54     }
55
56     public VPCUtil getVPCProxy() {
57         return this.VPCProxy;
58     }
59
60     public ECSUtil getECSProxy() {
61         return ECSProxy;
62     }
63
64     public SecurityGroupUtil getSecurityGroupProxy() {
65         return SecurityGroupProxy;
66     }
67
68     public PublicIPUtil getPublicIPProxy() {
69         return PublicIPProxy;
70     }
71
72 }

TokenProxy v0.3

  把这些工作(关键代码)都处理完之后,外部类调用这个类,就可以只通过这个类就拿到4个业务模块的函数,并且这些函数无需重复验证了;并且,如果后续要添加不同类型的业务API操作,直接在这个代理类上面处理就可以了(主要解决)。

图2. 用0.3版本TokenProxy代理之后,华为云API模块操作流程图

  优点: 1、减少系统相互依赖。 2、提高灵活性。 3、提高了安全性。

  缺点:不符合开闭原则,如果要改东西很麻烦,继承重写都不合适。(如果还有其他类型的业务API,代理类的初始化过程代码会更加繁杂)

  使用场景: 1、为复杂的模块或子系统提供外界访问的模块。 2、子系统相对独立。 3、预防低水平人员带来的风险。

  注意事项:在层次化结构中,可以使用外观模式定义系统中每一层的入口。

原文地址:https://www.cnblogs.com/dgutfly/p/11615085.html

时间: 2024-10-18 09:44:45

Fun论设计模式之3:外观模式(Facade Pattern)的相关文章

设计模式 - 外观模式(facade pattern) 详解

外观模式(facade pattern) 详解 本文地址: http://blog.csdn.net/caroline_wendy 外观模式(facade pattern): 提供了一个统一的接口, 用来访问子系统中的一群接口. 外观定义了一个高层接口, 让子系统更容易使用. 外观模式包含三个部分: 1. 子系统: 子类, 单个复杂子类 或 多个子类; 2. 外观(facade)类: 把子系统设计的更加容易使用; 3. 客户: 只需要调用外观类. 与适配器模式(adapter pattern)的

二十四种设计模式:外观模式(Facade Pattern)

外观模式(Facade Pattern) 介绍为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用. 示例有一个Message实体类,某对象对它的操作有Get()方法,另外还有一个对象有一个Validate()方法来判断用户是否有权限.现在提供一个高层接口来封装这两个方法. MessageModel using System; using System.Collections.Generic; using System.Text; nam

设计模式-10外观模式(Facade Pattern)

1.模式动机 在现实生活中,常常存在办事较复杂的例子,如办房产证或注册一家公司,有时要同多个部门联系,这时要是有一个综合部门能解决一切手续问题就好了. 软件设计也是这样,当一个系统的功能越来越强,子系统会越来越多,客户对系统的访问也变得越来越复杂.这时如果系统内部发生改变,客户端也要跟着改变,这违背了"开闭原则",也违背了"迪米特法则(最少知道原则)",所以有必要为多个子系统提供一个统一的接口,从而降低系统的耦合度,这就是外观模式的目标. 2.模式定义 外观模式(F

设计模式(结构型)之外观模式(Facade Pattern)

PS一句:最终还是选择CSDN来整理发表这几年的知识点,该文章平行迁移到CSDN.因为CSDN也支持MarkDown语法了,牛逼啊! [工匠若水 http://blog.csdn.net/yanbober] 阅读前一篇<设计模式(结构型)之装饰者模式(Decorator Pattern)>http://blog.csdn.net/yanbober/article/details/45395747 概述 一个客户类需要和多个业务类交互,而这些业务类经常会作为整体出现,由于涉及到的类比较多,导致使

设计模式学习心得&lt;外观模式 Facade&gt;

外观模式(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口.这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性. 这种模式涉及到一个单一的类,该类提供了客户端请求的简化方法和对现有系统类方法的委托调用. 概述 意图 为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用. 主要解决 降低访问复杂系统的内部子系统时的复杂度,简化客户端与之的接口. 何时使用 客户端不需要知道系统

设计模式之八:外观模式(Facade)

外观模式: 为子系统中的一系列接口提供了一个统一的界面.外观模式定义了一个高层次的接口以使子系统更加容易使用. Provide a unified interface to a set of interfaces in a subsystem. Fa?ade defines a higher-level interface that makes the subsystem easier to use. UML图: 主要包括: Facade(MortgageApplication):了解每个子系统

设计模式之【外观模式-Facade】

外观模式(Facade)外观模式是为了解决类与类之家的依赖关系的像spring一样,可以将类和类之间的关系配置到配置文件中而外观模式就是将他们的关系放在一个Facade类中降低了类类之间的耦合度,该模式中没有涉及到接口 一.3个基础类模式 package Facade; public class CPU { public void startup(){ System.out.println("cpu 启动!"); } public void shutdown(){ System.out

11.外观模式(Facade Pattern)

using System; namespace ConsoleApplication4 { class Program { /// <summary> /// 不使用外观模式的情况 /// 此时客户端与三个子系统都发送了耦合,使得客户端程序依赖与子系统 /// 为了解决这样的问题,我们可以使用外观模式来为所有子系统设计一个统一的接口 /// 客户端只需要调用外观类中的方法就可以了,简化了客户端的操作 /// 从而让客户和子系统之间避免了紧耦合 /// </summary> ///

研磨设计模式解析及python代码实现——(二)外观模式(Facade)

一.外观模式定义 为子系统中的一组接口提供一个一致的界面,使得此子系统更加容易使用. 二.书中python代码实现 1 class AModuleApi: 2 def testA(self): 3 pass 4 class AModuleImpl(AModuleApi): 5 def testA(self): 6 print "Now Call testA in AModule!" 7 class BModuleApi: 8 def testB(self): 9 pass 10 cla

设计模式之外观模式(Facade)摘录

23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于如何创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而一个对象创建型模式将实例化委托给另一个对象.创建型模式有两个不断出现的主旋律.第一,它们都将关于该系统使用哪些具体的类的信息封装起来.第二,它们隐藏了这些类的实例是如何被创建和放在一起的.整个系统关于这些对象所知道的是由抽象类所定义的接口.因此,创建型模式在什么被创建,谁创建它,它是怎样被创建的,以