使用策略模式优化过多的if else语句

2023-05-16

此处的过多是指if else超过三层,如下面的代码:

public class MainStart {

    public static void main(String[] args) {
        String message = "select";
        if(message.equals("select")){
            System.out.println("select command!");
        }else if (message.equals("abort")){
            System.out.println("abort command!");
        }else if (message.equals("add")){
            System.out.println("add command!");
        }else{
            System.out.println("no command!");
        }
    }
}

在上面的代码中,main方法根据message的类型处理不同的逻辑,此处if else使用过度,可以使用策略模式进行优化。

策略模式是一种解耦的方法,它对算法进行封装,使得算法的调用和算法本身分离。使用策略模式客户端代码不需要调整,算法之间可以互相替换,因为不同的算法实现的是同一个接口。将上面的代码优化后变为:

public class MainStart {

    public static void main(String[] args) {
        String message = "select";
        CommandContext commandContext = new CommandContext();
        CommandStrategy commandStrategy = commandContext.getInstance(message);
        commandStrategy.process(message);
    }
}

上面的commandContext.getInstance(message)根据message类型反射获取对象实例,再调用process(message)处理逻辑。

实现策略模式需要以下几个步骤:

1.定义接口

public interface CommandStrategy {

    void process(String message);
}

2.实现接口,重写处理逻辑

public class AbortCommand implements CommandStrategy {
    @Override
    public void process(String message) {
        System.out.println("command type:"+message);
    }
}
public class AddCommand implements CommandStrategy {

    @Override
    public void process(String message) {
        System.out.println("command type:"+message);

    }
}
public class SelectCommand implements CommandStrategy {
    @Override
    public void process(String message) {
        System.out.println("command type:"+message);

    }
}

3.定义策略上下文,根据message类型获取对象实例

public class CommandContext {
    public CommandStrategy getInstance(String commandType) {
        CommandStrategy commandStrategy = null;
        Map<String, String> allClazz = CommandEnum.getAllClazz();
        String clazz = allClazz.get(commandType.trim().toLowerCase());
        if (StringUtils.isNoneEmpty(clazz)) {
            try {
                try {
                    commandStrategy = (CommandStrategy) Class.forName(clazz).newInstance();//调用无参构造器创建实例
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        return commandStrategy;
    }
}

在这一步骤中,我们需要一种方式可以根据message类型来反射获取对象的实例,这里使用枚举来维护二者的对应关系。

public enum CommandEnum {

    SELECT("select", "com.jxz.java.demo.command.SelectCommand"), ADD("add", "com.jxz.java.demo.command.AddCommand"), ABORTED("abort", "com.jxz.java.demo.command.AbortCommand");
    private String command;
    private String clazz;

    public static Map<String, String> getAllClazz() {
        Map<String, String> map = new HashMap<>(8);
        for (CommandEnum commandEnum : CommandEnum.values()) {
            map.put(commandEnum.getCommand(), commandEnum.getClazz());
        }
        return map;
    }

    public String getCommand() {
        return command;
    }

    CommandEnum(String command, String clazz) {
        this.command = command;
        this.clazz = clazz;
    }

    public void setCommand(String command) {
        this.command = command;
    }

    public String getClazz() {
        return clazz;
    }

    public void setClazz(String clazz) {
        this.clazz = clazz;
    }

}

在上面的代码中,getAllClazz()方法用于获取所有message和对应处理类的映射关系。至此策略模式优化就已经完成了,运行MainStart可以看到运行结果。

但是这里还有一个不够优雅的地方,就是message类型和处理类的映射关系还是需要手动维护,不够智能,如果可以自动识别就比较方便了,如果新增业务逻辑,只需要再增加一个类就可以了。

因为参考了spring自动扫描包下类的方式,在此添加spring依赖:

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.1.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.1.5.RELEASE</version>
        </dependency>

工程目录结构如下:

util包中的ClassResourcePatternResolver类是查找command包中的所有类,此处实现了spring的资源接口ResourceLoaderAware,代码如下:

package com.jxz.java.demo.util;

import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternUtils;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;

import java.io.IOException;
import java.net.URL;
import java.util.LinkedHashSet;
import java.util.Set;

/**
 * @Author JiangXiaoZhi
 * @Date 2019/3/18 10:42
 * @ModifyDate 2019/3/18 10:42
 * @Version 1.0
 */
public class ClassResourcePatternResolver implements ResourceLoaderAware {

    private static ResourceLoader resourceLoader;

    public static Set<String> findAllClassPathResources() throws IOException {
        ResourcePatternResolver resolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
        MetadataReaderFactory metaReader = new CachingMetadataReaderFactory(resourceLoader);
        // 通过classpath
//        Resource[] resources = resolver.getResources("classpath*:com/jxz/java/demo/command/*.class");
        // 通过file
//        Resource[] resources = resolver.getResources("file:/F:/flink-demo/target/classes/com/jxz/java/demo/command/*.class");
        String classResourcesPath = getClassResourcesPath();
        Resource[] resources = resolver.getResources(classResourcesPath);
        Set<String> set = new LinkedHashSet<>(16);
        for (Resource r : resources) {
            MetadataReader reader = metaReader.getMetadataReader(r);
            String className = reader.getClassMetadata().getClassName();
            set.add(className);
        }
        return set;
    }

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }

    // 获取上一层command包目录
    private static String getClassResourcesPath() {
        URL url = ClassResourcePatternResolver.class.getResource("../");
        String protocol = url.getProtocol();
        String path = url.getPath();
        return protocol + ":" + path + "command/*.class";
    }
}
DynamicEnumUtil类动态添加枚举类型,
package com.jxz.java.demo.util;

import sun.reflect.ConstructorAccessor;
import sun.reflect.FieldAccessor;
import sun.reflect.ReflectionFactory;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @Author JiangXiaoZhi
 * @Date 2019/3/18 18:21
 * @ModifyDate 2019/3/18 18:21
 * @Version 1.0
 */
public class DynamicEnumUtil {
    private static ReflectionFactory reflectionFactory = ReflectionFactory.getReflectionFactory();

    private static void setFailsafeFieldValue(Field field, Object target, Object value) throws NoSuchFieldException,
            IllegalAccessException {

        // let's make the field accessible
        field.setAccessible(true);

        // next we change the modifier in the Field instance to
        // not be final anymore, thus tricking reflection into
        // letting us modify the static final field
        Field modifiersField = Field.class.getDeclaredField("modifiers");
        modifiersField.setAccessible(true);
        int modifiers = modifiersField.getInt(field);

        // blank out the final bit in the modifiers int
        modifiers &= ~Modifier.FINAL;
        modifiersField.setInt(field, modifiers);

        FieldAccessor fa = reflectionFactory.newFieldAccessor(field, false);
        fa.set(target, value);
    }

    private static void blankField(Class<?> enumClass, String fieldName) throws NoSuchFieldException,
            IllegalAccessException {
        for (Field field : Class.class.getDeclaredFields()) {
            if (field.getName().contains(fieldName)) {
                AccessibleObject.setAccessible(new Field[]{field}, true);
                setFailsafeFieldValue(field, enumClass, null);
                break;
            }
        }
    }

    private static void cleanEnumCache(Class<?> enumClass) throws NoSuchFieldException, IllegalAccessException {
        blankField(enumClass, "enumConstantDirectory"); // Sun (Oracle?!?) JDK 1.5/6
        blankField(enumClass, "enumConstants"); // IBM JDK
    }

    private static ConstructorAccessor getConstructorAccessor(Class<?> enumClass, Class<?>[] additionalParameterTypes)
            throws NoSuchMethodException {
        Class<?>[] parameterTypes = new Class[additionalParameterTypes.length + 2];
        parameterTypes[0] = String.class;
        parameterTypes[1] = int.class;
        System.arraycopy(additionalParameterTypes, 0, parameterTypes, 2, additionalParameterTypes.length);
        return reflectionFactory.newConstructorAccessor(enumClass.getDeclaredConstructor(parameterTypes));
    }

    private static Object makeEnum(Class<?> enumClass, String value, int ordinal, Class<?>[] additionalTypes,
                                   Object[] additionalValues) throws Exception {
        Object[] parms = new Object[additionalValues.length + 2];
        parms[0] = value;
        parms[1] = Integer.valueOf(ordinal);
        System.arraycopy(additionalValues, 0, parms, 2, additionalValues.length);
        return enumClass.cast(getConstructorAccessor(enumClass, additionalTypes).newInstance(parms));
    }

    /**
     * Add an enum instance to the enum class given as argument
     *
     * @param <T>      the type of the enum (implicit)
     * @param enumType the class of the enum to be modified
     * @param enumName the name of the new enum instance to be added to the class.
     */
    @SuppressWarnings("unchecked")
    public static <T extends Enum<?>> void addEnum(Class<T> enumType, String enumName, Class<?>[] additionalTypes, Object[] additionalValues) {

        // 0. Sanity checks
        if (!Enum.class.isAssignableFrom(enumType)) {
            throw new RuntimeException("class " + enumType + " is not an instance of Enum");
        }

        // 1. Lookup "$VALUES" holder in enum class and get previous enum instances
        Field valuesField = null;
        Field[] fields = enumType.getDeclaredFields();
        for (Field field : fields) {
            if (field.getName().contains("$VALUES")) {
                valuesField = field;
                break;
            }
        }
        AccessibleObject.setAccessible(new Field[]{valuesField}, true);

        try {

            // 2. Copy it
            T[] previousValues = (T[]) valuesField.get(enumType);
            List<T> values = new ArrayList<T>(Arrays.asList(previousValues));

            // 3. build new enum
            T newValue = (T) makeEnum(enumType, enumName, values.size(), additionalTypes, additionalValues);

            // 4. add new value
            values.add(newValue);

            // 5. Set new values field
            setFailsafeFieldValue(valuesField, null, values.toArray((T[]) Array.newInstance(enumType, 0)));

            // 6. Clean enum cache
            cleanEnumCache(enumType);

        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage(), e);
        }
    }
}
CommandEnum类稍作修改,先是动态添加了枚举类型,没有直接返回map类型,这样做是保证了类型安全。完整代码如下:
package com.jxz.java.demo.strategy;

import com.jxz.java.demo.util.ClassResourcePatternResolver;
import com.jxz.java.demo.util.DynamicEnumUtil;

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * @Author JiangXiaoZhi
 * @Date 2019/3/13 14:31
 * @ModifyDate 2019/3/13 14:31
 * @Version 1.0
 */
public enum CommandEnum {;

    //SELECT("select", "com.jxz.java.demo.command.SelectCommand"), ADD("add", "com.jxz.java.demo.command.AddCommand"), ABORTED("abort", "com.jxz.java.demo.command.AbortCommand");
    private String command;
    private String clazz;

    public static Map<String, String> getAllClazz() throws IOException {

        Set<String> set = ClassResourcePatternResolver.findAllClassPathResources();
        Iterator<String> it = set.iterator();
        while (it.hasNext()){
            String fullName = it.next();
            String command = fullName.substring(fullName.lastIndexOf(".")+1).replace("Command","").toLowerCase().trim();
            DynamicEnumUtil.addEnum(CommandEnum.class,command,new Class<?>[] {String.class,String.class},new Object[] {command,fullName});
//            map.put(command,fullName);
        }

//        for (CommandEnum commandEnum : CommandEnum.values()) {
//            map.put(commandEnum.getCommand(), commandEnum.getClazz());
//        }
        Map<String, String> map = new HashMap<>(8);
        for (CommandEnum value:CommandEnum.values()){
            String command = value.getCommand();
            String clazz = value.getClazz();
            map.put(command,clazz);
        }
        return map;
    }

    public String getCommand() {
        return command;
    }

    CommandEnum(String command, String clazz) {
        this.command = command;
        this.clazz = clazz;
    }

    public void setCommand(String command) {
        this.command = command;
    }

    public String getClazz() {
        return clazz;
    }

    public void setClazz(String clazz) {
        this.clazz = clazz;
    }

}

至此整个优化完成,尝试新加一个逻辑处理类,类的命名方式:message类型+Command:

package com.jxz.java.demo.command;

import com.jxz.java.demo.strategy.CommandStrategy;

/**
 * @Author JiangXiaoZhi
 * @Date 2019/3/18 19:51
 * @ModifyDate 2019/3/18 19:51
 * @Version 1.0
 */
public class DeleteCommand implements CommandStrategy {
    @Override
    public void process(String message) {
        System.out.println("command type:"+message);
    }
}

进行测试,结果如下:

结果正确,完。 

==========================================================================

上面的代码不够完善,进一步优化,就是在每一次调用commandContext.getInstance(message)方法获取实例时,都要调用getAllClazz()方法扫描包获取类名,这一步是冗余的,扫描包下面的类只需要进行一次即可,可以用静态代码块,也可以用单例模式,此处用静态代码块:

package com.jxz.java.demo.strategy;

import com.jxz.java.demo.util.ClassResourcePatternResolver;
import com.jxz.java.demo.util.DynamicEnumUtil;

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * @Author JiangXiaoZhi
 * @Date 2019/3/13 14:31
 * @ModifyDate 2019/3/13 14:31
 * @Version 1.0
 */
public enum CommandEnum {;

    private String command;
    private String clazz;
    public static Map<String, String> map = new HashMap<>(8);

    static {
        System.out.println("invoke static block......");
        Set<String> set = null;
        try {
            set = ClassResourcePatternResolver.findAllClassPathResources();
            Iterator<String> it = set.iterator();
            while (it.hasNext()){
                String fullName = it.next();
                String command = fullName.substring(fullName.lastIndexOf(".")+1).replace("Command","").toLowerCase().trim();
                DynamicEnumUtil.addEnum(CommandEnum.class,command,new Class<?>[] {String.class,String.class},new Object[] {command,fullName});
                for (CommandEnum value:CommandEnum.values()){
                    String cmd = value.getCommand();
                    String claz = value.getClazz();
                    map.put(command,claz);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public String getCommand() {
        return command;
    }

    CommandEnum(String command, String clazz) {
        this.command = command;
        this.clazz = clazz;
    }

    public void setCommand(String command) {
        this.command = command;
    }

    public String getClazz() {
        return clazz;
    }

    public void setClazz(String clazz) {
        this.clazz = clazz;
    }

}

运行主程序,查看静态代码块值调用了一次:

完。 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用策略模式优化过多的if else语句 的相关文章

  • MySql之索引

    通常小型项目涉及数据量比较小 xff0c 数据查询频率不高 xff0c 索引通常会被忽略 但当数据量较大 xff0c 涉及多个表 xff0c 查询较为频繁时 xff0c 我们需要对查询性能进行优化 xff0c 此时 xff0c 建立合适的索
  • jupyter-notebook二次开发

    背景 公司内部提供给算法人员用于模型训练的平台开发需求中提出了嵌入Jupyter Notebook模块 xff0c 而Jupyter Notebook是开源的 xff0c 方便后续对部分细节进行功能定制和优化 xff0c 需要对其进行调研
  • python中大数据文件读取

    python中大数据文件读取 python中经常会遇到读取大文件的场景 文件较小时 xff0c 我通常采用下面方法 xff0c readlines xff08 xff09 xff0c 该方法会一次性读取文件的所有行 xff0c 并将其放入l
  • Linux|奇怪的知识|locate命令---文件管理小工具

    前言 Linux的命令是非常多的 xff0c 有一些冷门的命令 xff0c 虽然很少用 xff0c 但可能会有意想不到的功能 xff0c 例如 xff0c 本文将要介绍的locate命令 xff08 平常很少会想到使用此命令 xff0c f
  • python之装饰器

    引言 软件开发中 xff0c 当需要创建高度重复的代码时 xff0c 需要寻求一种优雅的解决方案 python中的元编程即解决这类问题 xff0c 通过创建函数和类来修改 生成或包装已有的代码 装饰器就是python中用来包装函数的一种机制
  • docker容器中程序退出异常,GPU未释放

    1 问题描述 近期在docker容器中对一批数据通过算法进行清洗时 xff0c 当数据处理完成后发现进程未正常退出 xff0c GPU内存未正常释放 span class token punctuation span root 64 ai6
  • 初识Redis

    什么是Redis Remote Dictionary Server xff0c 即远程字典服务 xff0c 是一款开源的 基于内存也支持持久化的key value数据库 xff0c 提供多种语言API 通常应用于需要处理大规模数据读写的场景
  • python之闭包

    前言 闭包作为python高级特性中的一个 xff0c 初学总觉其披着一层神秘的面纱 xff0c 这里我们来一起揭开这层面纱吧 那什么是闭包呢 xff1f 闭包 xff0c 又称闭包函数 xff0c 和普通的嵌套函数类似 xff0c 闭包中
  • 三个基础排序算法

    排序在计算机算法中非常常见也非常基础 xff0c 不管是准备面试还是纯属兴趣 xff0c 掌握它都很有必要 选择排序 基本思想 xff1a 预置list i 为最小 xff0c 逐个比较range i len list 里的元素 xff0c
  • 数据结构之链表

    和顺序表相对应 xff0c 有个链式存储的数据结构 xff0c 命名曰链表 单链表 节点中只存储后项节点指针的链表 xff0c 称为单链表 定义节点 class LinkNode object def init self data 61 N
  • 数据结构之哈希表

    概念 哈希表是一种数据结构 xff0c 通过哈希函数来组织数据 xff0c 以支持快速插入和搜索 哈希表的关键思想是使用哈希函数将键映射到存储桶 更确切地说 xff0c 当我们插入一个新的键时 xff0c 哈希函数将决定该键应该分配到哪个桶
  • 图片数据清洗

    前言 数据对于深度学习算法模型的效果至关重要 通常 xff0c 在对采集到的大量数据进行标注前需要做一些数据清洗工作 对于大量的数据 xff0c 人工进行直接清洗速度会很慢 xff0c 因此开发一些自动化清洗工具对批量数据首先进行自动清洗
  • PyQt5 多线程实例

    前言 PyQt的所有窗口都在UI主线程中 xff0c 也就是main函数中执行了QApplication exec 的线程中 xff0c 在该线程中执行耗时较长的操作时 xff0c 会导致当前窗口停止响应 为了避免上述情况发生 xff0c
  • 模型评价标准

    机器学习 机器学习是通过一些让计算机可以自动学习的算法 xff0c 从数据中分析获得规律 xff0c 然后利用规律对新样本进行预测 评价标准 为了了解模型的泛化能力 xff0c 即判断模型的好坏 xff0c 我们需要用某个指标来衡量 xff
  • postgresql|数据库|【postgresql-12的基于pg_basebackup的主从复制部署】

    前言 xff1a postgresql数据库说实话是真心好用 xff0c 但 xff0c 想用好是比较困难的 那么 xff0c 造成该数据库使用困难的是它的内置工具非常的多 xff0c 并且整体优化是比较难的 比如 xff0c 自带的备份工
  • windows上的中文文件名上传到linux上乱码问题解决

    问题描述 有很多多层文件夹存放的数据保存在windows上 xff0c 文件夹和文件名均含有中文 xff0c 将这些文件目录传到linux上 xff0c 中文名显示乱码 问题分析 windows上中文默认编码格式是gbk xff0c 而li
  • JAVA 面试题经典(附答案)

    JAVA JAVA8大基本数据类型 J AVA8大基本数据类型 HashMap和Hashtable的比较 Hashtable xff1a 1 Hashtable不允许key或者value为null xff0c 线程安全 xff0c 实现线程
  • u盘写入映像时提示:主引导记录(mbr)写入失败!!

    在使用软件写入U盘镜像时 xff0c 出现下面的提示 xff1a 解决方法是使用DiskGenius重新建立MBR
  • debian SID安装笔记

    1 声卡设置问题 添加了声卡驱动 xff0c 但是进入桌面没有声音 xff1f 一般是没有给用户使用设备的权限 解决方法 xff1a adduser audio eg adduser jerry audio xff08 解决 xff09 你
  • ubuntu下vncserver配置

    Ubuntu下设置VNCServer Virtual Network Computing VNC 是进行远程桌面控制的一个软件 客户端的键盘输入和鼠标操作通过网络传输到远程服务器 xff0c 控制服务器的操作 服务器的图形界面通过网络传输会

随机推荐

  • vsftp配置实例-虚拟用户锁定目录

    一 实验步骤 1 创建用户 创建ftpuser1登录用户 useradd g ftp d share soft s sbin nologin ftpuser1 为ftpuser1设置登录密码 passwd ftpuser1 2 编辑配置文件
  • 基于51的光立方制作

    单片机入门者必然会从点亮一盏LED灯开始 xff0c 如果LED数量比较多 xff0c 就不能使用单个引脚去控制 xff0c 例如光立方 xff0c 利用锁存器和人体的视觉暂留效果就可以占用少量引脚实现光立方 所需材料 xff1a STC8
  • 如何实现无界面Android app

    如何实现无界面Android app 前言代码实现AndroidManifest xmlMainActivity javaMyService java 前言 在Android开发中 xff0c 可能会遇到只需要在后台运行服务 xff0c 不
  • 惊呆面试官的回答:HashMap和TreeMap的区别

    前几天 xff0c 有一位粉丝在直播间问了我这样一个问题 xff0c 说HashMap和TreeMap有什么区别 今天 xff0c 我给大家分享一下我的理解 1 两者区别 我们知道不管是HashMap还是TreeMap xff0c 都是通过
  • postgresql|【基于pg_basebackup命令的归档备份和恢复---热备冷恢复方式】

    一 xff0c 基本原理和步骤 备份 xff1a 使用pg basebackup命令来进行备份 xff0c 这个命令可以将postgresql的数据文件备份为两个压缩文件 xff1a base tar和 pg wal tar 本别是数据文件
  • js获取对象属性的两种方式

    一 如果属性名称是常量 xff08 固定值 xff09 xff0c 获取属性值的方式有 xff1a 1 对象 属性名称 如 obj age 2 对象 属性名称 如 obj age 二 如果属性名称是一个变量 xff0c 值不固定 xff0c
  • 关于Eclipse的Unhandled event loop exception No more handles

    今天用了公司一台电脑做开发 xff0c 在运行eclipse以及myeclipse点击java代码窗口内部时 xff0c 都遇到如下图所示的问题 xff1a 上网查了一下错误的原因 xff1a 因为一些进程和eclipse起了冲突 下面我来
  • IDEA较新版本,编译xml文件(src/main/java下的xml等)

    IDEA较新版编译src main java下的文件 问题 xff1a 原因 xff1a 解决 xff1a 实际应用代码 xff1a 问题 xff1a 在导入新项目时 xff0c 由于项目中整合了Mybatis xff0c 一些mapper
  • IDEA 2018.3.2 版本配置SVN

    IDEA 2018 3 2 版本配置SVN 1 首先安装TortoiseSVN2 配置IDEA3 IDEA开启SVN 1 首先安装TortoiseSVN 安装的过程中 xff0c 需要勾选command line client tools
  • springmvc 上传文件,单个文件,多个文件

    1 Java代码部分 xff1a 1 1spring配置 xff1a span class token operator lt span span class token operator span span class token ope
  • Jquery实现免上传预览图片功能

    Demo如下 span class token doctype lt DOCTYPE html gt span span class token tag span class token tag span class token punct
  • jQuery :not() 选择器

    JQ选择器 xff0c 不选择某些标签 基础用法 xff1a p not class 多个not p not class not id span class token doctype lt DOCTYPE html gt span spa
  • 弱智笔记 js用==比较 空字符串==0,返回true

    span class token keyword if span span class token punctuation span span class token string 34 34 span span class token o
  • PHP7+apache2.4环境搭建

    PHP 43 apache环境搭建 版本 xff1a PHP Version 7 1 30 apache2 4 下载 xff1a 下载php时 xff0c 注意下载VC14 x64 Thread Safe xff0c 否则没有php7apa
  • JAVA构造器注意事项

    JAVA构造器 1 JAVA默认提供无参构造器 2 默认无参构造器 对域进行初始化规则 数值型 xff1a 0 布尔类型 xff1a false 对象类型 xff1a null 3 如果自己写了一个带参构造器 xff0c 默认的无参构造器失
  • 原生大数据|elasticSearch|低版本kibana组件的汉化

    前言 xff1a 大数据的范畴里包括EFK ELK xff0c 这些套件安装部署是非常的成熟 xff0c 因此是比较好部署安装的 xff0c 一般的 xff0c 困难出现在部署完成后的运营和维护 kibana这个组件的版本低于7我们就应该认
  • JAVA继承-注意事项

    JAVA继承 1 子类所有构造器 xff0c 会隐式调用父类的无参构造器 原理 xff1a 子类所有构造器 xff0c 都会在第一行隐式调用super 问题 xff1a 如果父类没有无参构造器 xff0c 编译报错 解决 xff1a 在子类
  • mac上安装brew出错curl: Failed to connect to raw.githubusercontent.com port 443解决方法

    问题描述 由于最近重做了电脑系统 xff0c 重新下载安装brew 就报错了 xff0c raw githubusercontent com 在国内由于不可描述的原因就无法访问 解决方法一 参考网上的解决方法 首先是访问这个网址 https
  • Hexo + gitHub pages

    网址 xff1a https oldmee github io hexo的写作流程就是会按照日期自动帮你归类 xff0c 你new了一个page会生成一个markdown文件 xff0c 你就可以愉快的写作了 xff0c 边写边看效果 xf
  • 使用策略模式优化过多的if else语句

    此处的过多是指if else超过三层 xff0c 如下面的代码 xff1a public class MainStart public static void main String args String message 61 34 se