作者:小傅哥
博客:https://bugstack.cn

沉淀、分享、发展,让自己和他人都能有所收获!

一、前言

对于代码你有编程感受吗

许多人写代码往往是没有编程感受的,也就是除了可以把功效根据牢固的流程编写出流水式的代码外,很难去思索整套功效服务的扩展性和可维护性。尤其是在一些较大型的功效搭建上,对照缺失一些驾驭能力,从而导致最终的代码相对来说不能做到精美绝伦。

江洋大盗与江洋大偷

两个本想形貌一样的意思的词,只因一字只差就让人以为一个是好牛,一个好搞笑。往往我们去开发编程写代码时也经常将一些不适当的用法用于营业需求实现中,当却不能意识到。一方面是由于编码不多缺少较大型项目的实践,另一方面是不思进取的总在以完成需求为目的缺少千锤百炼的工匠精神。

书从来不是看的而是用的

在这个学习资料险些爆炸的时代,甚至你可以容易就获取几个T的视频,小手轻轻一点就珍藏一堆文章,但却很少去看。学习的历程从不只是简朴的看一遍就可以,对于一些实操性的手艺书籍,若是真的希望学习到知识,那么一定是把这本书用起来而绝对不是看起来。

二、开发环境

  1. JDK 1.8
  2. Idea + Maven
  3. 涉及工程三个,可以通过关注民众号bugstack虫洞栈,回复源码下载获取(打开获取的链接,找到序号18)
工程 形貌
itstack-demo-design-9-00 场景模拟工程;模拟单点登录类
itstack-demo-design-9-01 使用一坨代码实现营业需求
itstack-demo-design-9-02 通过设计模式优化革新代码,发生对比性从而学习

三、装饰器模式先容

初看上图感受装饰器模式有点像俄罗斯套娃、某众汽车,而装饰器的焦点就是再不改原有类的基础上给类新增功效。不改变原有类,可能有的小伙伴会想到继续、AOP切面,固然这些方式都可以实现,然则使用装饰器模式会是另外一种思绪更为天真,可以制止继续导致的子类过多,也可以制止AOP带来的复杂性。

你熟悉的场景许多用到装饰器模式

new BufferedReader(new FileReader(""));,这段代码你是否熟悉,信赖学习java开发到字节省、字符流、文件流的内容时都见到了这样的代码,一层嵌套一层,一层嵌套一层,字节省转字符流等等,而这样方式的使用就是装饰器模式的一种体现。

四、案例场景模拟

在本案例中我们模拟一个单点登录功效扩充的场景

一样平常在营业开发的初期,往往内部的ERP使用只需要判断账户验证即可,验证通事后即可接见ERP的所有资源。但随着营业的不停发展,团队里最先泛起专门的运营职员、营销职员、数据职员,每个职员对于ERP的使用需求差别,有些需要创建活动,有些只是查看数据。同时为了保证数据的安全性,不会让每个用户都有最高的权限。

那么以往使用的SSO是一个组件化通用的服务,不能在内里添加需要的用户接见验证功效。这个时刻我们就可以使用装饰器模式,扩充原有的单点登录服务。但同时也保证原有功效不受损坏,可以继续使用。

1. 场景模拟工程

itstack-demo-design-9-00
└── src
    └── main
        └── java
            └── org.itstack.demo.design
                ├── HandlerInterceptor.java
                └── SsoInterceptor.java
  • 这里模拟的是spring中的类:HandlerInterceptor,实现起接口功效SsoInterceptor模拟的单点登录阻挡服务。
  • 为了制止引入太多spring的内容影响对设计模式的阅读,这里使用了同名的类和方式,尽可能削减外部的依赖。

2. 场景简述

2.1 模拟Spring的HandlerInterceptor

public interface HandlerInterceptor {

    boolean preHandle(String request, String response, Object handler);

}
  • 现实的单点登录开发会基于;org.springframework.web.servlet.HandlerInterceptor 实现。

2.2 模拟单点登录功效

public class SsoInterceptor implements HandlerInterceptor{

    public boolean preHandle(String request, String response, Object handler) {
        // 模拟获取cookie
        String ticket = request.substring(1, 8);
        // 模拟校验
        return ticket.equals("success");
    }

}
  • 这里的模拟实现异常简朴只是截取字符串,现实使用需要从HttpServletRequest request工具中获取cookie信息,剖析ticket值做校验。
  • 在返回的内里也异常简朴,只要获取到了success就认为是允许登录。

五、用一坨坨代码实现

此场景大多数实现的方式都市接纳继续类

继续类的实现方式也是一个对照通用的方式,通过继续后重写方式,并发将自己的逻辑笼罩进去。若是是一些简朴的场景且不需要不停维护和扩展的,此类实现并不会有什么,也不会导致子类过多。

1. 工程结构

itstack-demo-design-9-01
└── src
    └── main
        └── java
            └── org.itstack.demo.design
                └── LoginSsoDecorator.java
  • 以上工程结构异常简朴,只是通过 LoginSsoDecorator 继续 SsoInterceptor,重写方式功效。

2. 代码实现

public class LoginSsoDecorator extends SsoInterceptor {

    private static Map<String, String> authMap = new ConcurrentHashMap<String, String>();

    static {
        authMap.put("huahua", "queryUserInfo");
        authMap.put("doudou", "queryUserInfo");
    }

    @Override
    public boolean preHandle(String request, String response, Object handler) {
        // 模拟获取cookie
        String ticket = request.substring(1, 8);
        // 模拟校验
        boolean success = ticket.equals("success");

        if (!success) return false;

        String userId = request.substring(9);
        String method = authMap.get(userId);

        // 模拟方式校验
        return "queryUserInfo".equals(method);
    }

}
  • 以上这部门通过继续重写方式,将小我私家可接见哪些方式的功效添加到方式中。
  • 以上看着代码还算对照清晰,但若是是对照复杂的营业流程代码,就会很杂乱。

3. 测试验证

3.1 编写测试类

@Test
public void test_LoginSsoDecorator() {
    LoginSsoDecorator ssoDecorator = new LoginSsoDecorator();
    String request = "1successhuahua";
    boolean success = ssoDecorator.preHandle(request, "ewcdqwt40liuiu", "t");
    System.out.println("登录校验:" + request + (success ? " 放行" : " 阻挡"));
}
  • 这里模拟的相当于登录历程中的校验操作,判断用户是否可登录以及是否可接见方式。

3.2 测试效果

登录校验:1successhuahua 阻挡

Process finished with exit code 0
  • 从测试效果来看知足我们的预期,已经做了阻挡。若是你在学习的历程中,可以实验模拟单点登录并继续扩展功效。

六、装饰器模式重构代码

接下来使用装饰器模式来举行代码优化,也算是一次很小的重构。

装饰器主要解决的是直接继续下因功效的不停横向扩展导致子类膨胀的问题,而是用装饰器模式后就会比直接继续显得加倍天真同时这样也就不再需要思量子类的维护。

在装饰器模式中有四个对照重要点抽象出来的点;

  1. 抽象构件角色(Component) - 界说抽象接口
  2. 详细构件角色(ConcreteComponent) - 实现抽象接口,可以是一组
  3. 装饰角色(Decorator) - 界说抽象类并继续接口中的方式,保证一致性
  4. 详细装饰角色(ConcreteDecorator) - 扩展装饰详细的实现逻辑

通过以上这四项来实现装饰器模式,主要焦点内容会体现在抽象类的界说和实现上。

1. 工程结构

itstack-demo-design-9-02
└── src
    └── main
        └── java
            └── org.itstack.demo.design
                ├── LoginSsoDecorator.java
                └── SsoDecorator.java

装饰器模式模子结构

  • 以上是一个装饰器实现的类图结构,重点的类是SsoDecorator,这个类是一个抽象类主要完成了对接口HandlerInterceptor继续。
  • 当装饰角色继续接口后会提供组织函数,入参就是继续的接口实现类即可,这样就可以很利便的扩展出差别功效组件。

2. 代码实现

2.1 抽象类装饰角色

public abstract class SsoDecorator implements HandlerInterceptor {

    private HandlerInterceptor handlerInterceptor;

    private SsoDecorator(){}

    public SsoDecorator(HandlerInterceptor handlerInterceptor) {
        this.handlerInterceptor = handlerInterceptor;
    }

    public boolean preHandle(String request, String response, Object handler) {
        return handlerInterceptor.preHandle(request, response, handler);
    }

}
  • 在装饰类中有两个重点的地方是;1)继续了处置接口、2)提供了组织函数、3)笼罩了方式preHandle
  • 以上三个点是装饰器模式的焦点处置部门,这样可以踢掉对子类继续的方式实现逻辑功效扩展。

2.2 装饰角色逻辑实现

public class LoginSsoDecorator extends SsoDecorator {

    private Logger logger = LoggerFactory.getLogger(LoginSsoDecorator.class);

    private static Map<String, String> authMap = new ConcurrentHashMap<String, String>();

    static {
        authMap.put("huahua", "queryUserInfo");
        authMap.put("doudou", "queryUserInfo");
    }

    public LoginSsoDecorator(HandlerInterceptor handlerInterceptor) {
        super(handlerInterceptor);
    }

    @Override
    public boolean preHandle(String request, String response, Object handler) {
        boolean success = super.preHandle(request, response, handler);
        if (!success) return false;
        String userId = request.substring(8);
        String method = authMap.get(userId);
        logger.info("模拟单点登录方式接见阻挡校验:{} {}", userId, method);
        // 模拟方式校验
        return "queryUserInfo".equals(method);
    }
}
  • 在详细的装饰类实现中,继续了装饰类SsoDecorator,那么现在就可以扩展方式;preHandle
  • preHandle的实现中可以看到,这里只体贴扩展部门的功效,同时不会影响原有类的焦点服务,也不会由于使用继续方式而导致的多余子类,增添了整体的天真性。

3. 测试验证

3.1 编写测试类

@Test
public void test_LoginSsoDecorator() {
    LoginSsoDecorator ssoDecorator = new LoginSsoDecorator(new SsoInterceptor());
    String request = "1successhuahua";
    boolean success = ssoDecorator.preHandle(request, "ewcdqwt40liuiu", "t");
    System.out.println("登录校验:" + request + (success ? " 放行" : " 阻挡"));
}
  • 这里测试了对装饰器模式的使用,通过透传原有单点登录类new SsoInterceptor(),通报给装饰器,让装饰器可以执行扩充的功效。
  • 同时对于通报者和装饰器都可以是多组的,在一些现实的营业开发中,往往也是由于太多类型的子类实现而导致不易于维护,从而使用装饰器模式替换。

3.2 测试效果

23:50:50.796 [main] INFO  o.i.demo.design.LoginSsoDecorator - 模拟单点登录方式接见阻挡校验:huahua queryUserInfo
登录校验:1successhuahua 放行

Process finished with exit code 0
  • 效果相符预期,扩展了对方式阻挡的校验性。
  • 若是你在学习的历程中有用到过单点上岸,那么可以适当在内里举行扩展装饰器模式举行学习使用。
  • 另外,另有一种场景也可以使用装饰器。例如;你之前使用某个实现某个接口吸收单个新闻,但由于外部的升级变为发送list聚集新闻,但你又不希望所有的代码类都去修改这部门逻辑。那么可以使用装饰器模式举行适配list聚集,给使用者依然是for循环后的单个新闻。

七、总结

  • 使用装饰器模式知足单一职责原则,你可以在自己的装饰类中完成功效逻辑的扩展,而不影响主类,同时可以按需在运行时添加和删除这部门逻辑。另外装饰器模式与继续父类重写方式,在某些时刻需要按需选择,并不一定某一个就是最好。
  • 装饰器实现的重点是对抽象类继续接口方式的使用,同时设定被继续的接口可以通过组织函数通报其实现类,由此增添扩展性并重写方式里可以实现此部门父类实现的功效。
  • 就像炎天热你穿短裤,冬天冷你穿棉裤,雨天挨浇你穿雨衣一样,你的基本自己没有被改变,而你的需求却被差别的装饰而实现。生涯中往往触目皆是设计,当你可以融合这部门活龙活现的例子到代码实现中,往往会创造出加倍优雅的实现方式。

八、推荐阅读

  • 1. 重学 Java 设计模式:实战工厂方式模式(多种类型商品发奖场景)
  • 2. 重学 Java 设计模式:实战抽象工厂模式(替换Redis双集群升级场景)
  • 3. 重学 Java 设计模式:实战制作者模式(装修物料组合套餐选配场景)
  • 4. 重学 Java 设计模式:实战原型模式(多套试每人问题和谜底乱序场景)
  • 5. 重学 Java 设计模式:实战桥接模式(多支付渠道「微信、支付宝」与多支付模式「刷脸、指纹」场景)
  • 6. 重学 Java 设计模式:实战组合模式(营销差异化人群发券,决策树引擎搭建场景)
,

欧博注册网址

www.cx11gw.cn欢迎进入欧博网址(Allbet Gaming),欧博网址开放会员注册、代理开户、电脑客户端下载、苹果安卓下载等业务。

声明:该文看法仅代表作者自己,与Sunbet 申博无关。转载请注明:欧博亚洲官方注册:重学 Java 设计模式:实战装饰器模式(SSO单点登录功效扩展,增添阻挡用户接见方式局限场景)
评论关闭

分享到:

影/人形立牌逊掉 热火LED墙播观众影片还会喊「防守」