zoukankan      html  css  js  c++  java
  • Fun论设计模式之3:外观模式(Facade Pattern)与华为云API类设计之二

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

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

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

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

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

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

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

  • 相关阅读:
    [转]Article: Invalid cross-thread operations
    【转】20余个国外免费英文电子书下载网站
    [转]推荐国外SQL Server学习网站
    【转】C#中的序列化和反序列化是什么、有什么作用、使用方法详解
    [转]How I explained OOD to my wife
    [转]How I explained Design Patterns to my wife: Part 1
    git和gitee的安装、上传和下载(一)
    【工作备忘】python读取oracle写入csv遇到的问题
    处理基地营地 html的python环境设置 (给同事参考的)
    爬虫scrapy-begin
  • 原文地址:https://www.cnblogs.com/dgutfly/p/11615085.html
Copyright © 2011-2022 走看看