• Java 关于策略模式+简单工厂模式下的思考


    导读

      最近在做公司一个消息网关的服务,包括:短信、微信、邮件等,所有请求通过一个入口,方便接口的管理(记录日志、接口限流白名单啥的)。如何写这个接口呢,还有为了以后扩展,对接过短信、微信、公众号的童鞋大概都了解,首先定义一个模板,然后后台传入json,替换模板中的值,然后发送。设计框架大概思路是这样的

    1. 第一层:通过策略模式,选择出具体的发送类型,比如:短信、微信、邮件。。。。。
    2. 第二层:再次通过策略模式,选择出具体的第三方平台,比如短信平台:阿里云、腾讯云、华为云。。。。。。
    3. 第三层:通过一个简单的工厂,选择出具体的模板,然后发送出去

      第一二层,以后可能会扩展出2、3家第三方平台,使用策略模式还是可以接受的,但是到了第三层的话,可能会出现一二十个模板,这样子的话,会出现一大堆if else等等(写过简单工厂的都清楚),然后自己手动封装一个工具类,获取一个类下的所有子类,然后通过一个字段创建对象,这里我做了一个优化,找到的值,我会先放到一个Map中,第二次请求来的时候,先去Map中查询下,是否有值,有值的话,直接调用,没有值的话,才会去重新找一遍,这样子性能也得到了提高

    项目结构

    工具类

    package com.ybchen.messagegateway;
    
    import java.io.File;
    import java.net.URL;
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @ClassName:TestMain
     * @Description:TODO
     * @Author:chenyb
     * @Date:2020/12/1 9:19 上午
     * @Versiion:1.0
     */
    public class TestMain {
        public static void main(String[] args) throws Exception {
                System.out.println("接口实现类:");
                for (Class<?> c : getAllAssignedClass(AbsClassA.class)) {
                    if (c.getName().contains("D")){
                        AbsClassA obj =(AbsClassA) c.newInstance();
                        obj.speak();
                    }
                    System.out.println(c.getName());
                }
                System.out.println("子类:");
                for (Class<?> c : getAllAssignedClass(AbsClassA.class)) {
                    System.out.println(c.getName());
                }
        }
    
        /**
         *  获取同一路径下所有子类或接口实现类
         *  
         *  @param intf
         *  @return
         *  @throws IOException
         *  @throws ClassNotFoundException
         */
        public static List<Class<?>> getAllAssignedClass(Class<?> cls) throws Exception {
            List<Class<?>> classes = new ArrayList<>();
            for (Class<?> c : getClasses(cls)) {
                if (cls.isAssignableFrom(c) && !cls.equals(c)) {
                    classes.add(c);
                }
            }
            return classes;
        }
    
        /**
         *  取得当前类路径下的所有类
         *  
         *  @param cls
         *  @return
         *  @throws IOException
         *  @throws ClassNotFoundException
         */
        public static List<Class<?>> getClasses(Class<?> cls) throws Exception {
            String pk = cls.getPackage().getName();
            String path = pk.replace('.', '/');
            ClassLoader classloader = Thread.currentThread().getContextClassLoader();
            URL url = classloader.getResource(path);
            return getClasses(new File(url.getFile()), pk);
        }
    
        /**
         *  迭代查找类
         *  
         *  @param dir
         *  @param pk
         *  @return
         *  @throws ClassNotFoundException
         */
        private static List<Class<?>> getClasses(File dir, String pk) throws ClassNotFoundException {
            List<Class<?>> classes = new ArrayList<>();
            if (!dir.exists()) {
                return classes;
            }
            for (File f : dir.listFiles()) {
                if (f.isDirectory()) {
                    classes.addAll(getClasses(f, pk + "." + f.getName()));
                }
                String name = f.getName();
                if (name.endsWith(".class")) {
                    classes.add(Class.forName(pk + "." + name.substring(0, name.length() - 6)));
                }
            }
            return classes;
        }
    }
    package com.ybchen.messagegateway;
    
    /**
     * @ClassName:AbsClassA
     * @Description:TODO
     * @Author:chenyb
     * @Date:2020/12/1 9:16 上午
     * @Versiion:1.0
     */
    public abstract class AbsClassA {
        public abstract void speak();
    }
    AbsClassA
    package com.ybchen.messagegateway;
    
    /**
     * @ClassName:ClassB
     * @Description:TODO
     * @Author:chenyb
     * @Date:2020/12/1 9:16 上午
     * @Versiion:1.0
     */
    public class ClassB extends AbsClassA {
        @Override
        public void speak() {
            System.out.println("BBBBBBB");
        }
    }
    ClassB
    package com.ybchen.messagegateway;
    
    /**
     * @ClassName:ClassC
     * @Description:TODO
     * @Author:chenyb
     * @Date:2020/12/1 9:16 上午
     * @Versiion:1.0
     */
    public class ClassC extends AbsClassA{
        @Override
        public void speak() {
            System.out.println("CCC");
        }
    }
    ClassC
    package com.ybchen.messagegateway.de;
    
    import com.ybchen.messagegateway.AbsClassA;
    
    /**
     * @ClassName:ClassD
     * @Description:TODO
     * @Author:chenyb
     * @Date:2020/12/1 9:17 上午
     * @Versiion:1.0
     */
    public class ClassD extends AbsClassA {
        @Override
        public void speak() {
            System.out.println("ddd");
        }
    }
    ClassD
  • 相关阅读:
    面向对象的特征有哪些方面?
    构造器(constructor)是否可被重写(override)?
    swtich 是否能作用在byte 上,是否能作用在long 上,是否能作用在String上?
    Java的运算符
    staitc关键字
    final关键字
    java的基本知识技能(二)
    java的基本操作和基本知识技能
    java概述------
    java中有几种方法实现一个线程?用什么关键字修饰同步方法?stop()和suspend()方法为何不推荐使用?
  • 原文地址:https://www.cnblogs.com/chenyanbin/p/14066939.html
Copyright © 2020-2023  润新知