面向接口的开发到面向对象的编程

  估计看到这个博文名字会有很些人懵逼,其实懵逼是正常的,因为刚听到这个名字我也是出于懵逼状态,也是看过类似的博文之后才有了那么点点的了解。

  一、面向接口的编程

    面向接口的编程目的是为了更好的代码扩展,因为对于java语言而言允许向上转型。

  二、面向对象的开发

    对于java世界而言,所有现实中的和非现实的事物一切都是可以抽象化的,万物皆对象。

  如何抽象化接口为java中的对象?

  接口包含了接口和抽象类,那么这里最终我们最关心的其实还是抽象方法。那么我们是否可以把方法看到一个对象?姑且可以,那么我们方法自身存在的那些属性?

    属性:方法名, 形参,返回值。

    行为:

      1、根据调用的方法执行某些行为(无形参,无返回值)

      2、根据调用的方法执行某些行为(有形参,无返回值)

      3、根据调用的方法执行某些行为(无形参,有返回值)

      3、根据调用的方法执行某些行为(有形参,有返回值)

  定义方法的抽象类(也可以接口)

 1 /**
 2  * 作者:liemng on 2017/11/15
 3  * 邮箱:859686819@qq.com
 4  */
 5 
 6 public abstract class Function {
 7 
 8     public String mFunctionName;
 9 
10     public Function(String functionName){
11         this.mFunctionName = functionName;
12     }
13 }

  这里定义抽象类Function,并且定义一个传入方法名字的构造函数。

  接下来咱们按照上班的行为顺序定义如下Function的子类.

  FunctionNoParamsNoResult 无形参无返回值类,并且定义抽象方法invoke()

 1 /**
 2  * 作者:liemng on 2017/11/15
 3  * 邮箱:859686819@qq.com
 4  */
 5 
 6 public abstract class FunctionNoParamsNoResult extends Function {
 7     public FunctionNoParamsNoResult(String functionName) {
 8         super(functionName);
 9     }
10 
11     public abstract void invoke();
12 }

  FunctionWithParamsOnly 有形参无返回值类,并且定义抽象方法invoke(params) 由于参数类型是未知故而采用了泛型

 1 /**
 2  * 作者:liemng on 2017/11/15
 3  * 邮箱:859686819@qq.com
 4  */
 5 
 6 public abstract class FunctionWithParamsOnly extends Function {
 7     public FunctionWithParamsOnly(String functionName) {
 8         super(functionName);
 9     }
10 
11     public abstract <Params> void invoke(Params params);
12 }

  FunctionWithResultOnly  无形参有返回值类,并且定义了抽象方法invoke()

 1 /**
 2  * 作者:liemng on 2017/11/15
 3  * 邮箱:859686819@qq.com
 4  */
 5 
 6 public abstract class FunctionWithResultOnly extends Function {
 7 
 8     public FunctionWithResultOnly(String functionName) {
 9         super(functionName);
10     }
11 
12     public abstract  <Result> Result invoke();
13 }

  FunctionWithParamsAndResult 有形参有返回值类,并且定义了抽象方法invoke(params) 由于参数类型是未知故而采用了泛型

 1 /**
 2  * 作者:liemng on 2017/11/15
 3  * 邮箱:859686819@qq.com
 4  */
 5 
 6 public abstract class FunctionWithParamsAndResult extends Function {
 7     public FunctionWithParamsAndResult(String functionName) {
 8         super(functionName);
 9     }
10 
11     public abstract  <Result, Params> Result invoke(Params params);
12 }

  到这里进步完成了对象的行为和属性的定义,对于属性由于是是未知的,故而直接使用了泛型。

  那么接下来就是如何去使用定义的方法类。这里我们添加如下管理类FunctionManager。

  根据上述的定义我们知道这里对于方法的行为我们这里定义了四种行为,那么我们这里简单的通过注解添加个约束。见代码

 1     public static final int TYPE_WITH_RESULT_ONLY = 0;
 2     public static final int TYPE_WITH_PARAMS_ONLY = 1;
 3     public static final int TYPE_NO_PARAMS_NO_RESULT = 2;
 4     public static final int TYPE_WITH_PARAMS_AND_RESULT = 3;
 5 
 6 
 7     /*由于方法行为仅仅存在四种,故而这里仅仅允许添加四种Action*/
 8     @IntDef({TYPE_WITH_RESULT_ONLY, TYPE_WITH_PARAMS_ONLY, TYPE_NO_PARAMS_NO_RESULT, TYPE_WITH_PARAMS_AND_RESULT})
 9     @Target(ElementType.PARAMETER)
10     @Retention(RetentionPolicy.SOURCE)
11     public @interface Type {
12     }

  这里我们看到注解类Type被注解@IntDef注解,这里说下@IntDef这里是约束警告元注解。这里拿方法的形参来简单讲解下该注解,该注解接受整形数据作为参数,并且被该元注解注解的注解用在方法的整形的形参上之后,这个形参对应的值必须是元注解中传入的任意一个值,否则就提示警告错误。这里我们用来约束方法的行为。

  根据对应的方法行为来存储对应的方法对象。

 1     private Map<Integer, List<? super Function>> mFuncMap;
 2     
 3     /**
 4      * 根据特定的Type添加对应的Function
 5      * @param type
 6      * @param funcName
 7      * @param function
 8      */
 9     public void addFunc(@Type int type, @NonNull String funcName, @NonNull Function function) {
10         if (TextUtils.isEmpty(funcName) || null == function) {
11             return;
12         }
13         List<? super Function> funcWithResult = mFuncMap.get(type);
14         if (funcWithResult.contains(function))
15             return;
16         funcWithResult.add(function);
17     }

  第九行我们看到我们的注解Type约束了对应的形参,这里也就是我们的约束。mFuncMap是用于存储对应的行为的方法对象。

  这个方法最重要的目的是完成对应的方法对象的添加。

  接下是添加的方法如何被一一有效的调用执行。那么这里我们仅仅简单的看下对应的调用无形参无返回值的方法调用,其他的都基本类似,我们直接忽略。

  调用无形参无返回值。那么可以根据对应的方法名找到对应的方法对象,调用对应的invoke方法。如下见代码:

 1     /**
 2      * 调用无形参 无返回值的方法
 3      * @param funcName 方法名
 4      * @return
 5      */
 6     public void invokeFuncWithParamsAndResult(@NonNull String funcName) {
 7         /*filter invalid tag*/
 8         if (TextUtils.isEmpty(funcName))
 9             return;
10         List<? super Function> funcList = mFuncMap.get(TYPE_NO_PARAMS_NO_RESULT);
11 
12         /*inner filter invalid tag*/
13         if (null == funcList || funcList.size() <= 0)
14             return;
15 
16         FunctionNoParamsNoResult func;
17         for (Object obj : funcList) {
18             func = ((FunctionNoParamsNoResult) obj);
19             if (funcName.equals(func.mFunctionName)) {
20                 func.invoke();
21             }
22         }
23     }

  FunctionManager的完整代码如下:

/**
 * 作者:liemng on 2017/11/15
 * 邮箱:859686819@qq.com
 */

public class FunctionManager {

    public static final String TAG = Function.class.getSimpleName();

    public static final int TYPE_WITH_RESULT_ONLY = 0;
    public static final int TYPE_WITH_PARAMS_ONLY = 1;
    public static final int TYPE_NO_PARAMS_NO_RESULT = 2;
    public static final int TYPE_WITH_PARAMS_AND_RESULT = 3;


    /*由于方法行为仅仅存在四种,故而这里仅仅允许添加四种Action*/
    @IntDef({TYPE_WITH_RESULT_ONLY, TYPE_WITH_PARAMS_ONLY, TYPE_NO_PARAMS_NO_RESULT, TYPE_WITH_PARAMS_AND_RESULT})
    @Target(ElementType.PARAMETER)
    @Retention(RetentionPolicy.SOURCE)
    public @interface Type {
    }

    private FunctionManager() {
        /*存储 需要返回值的Function*/
        List<? super Function> funcWithResult = new ArrayList<>();
        /*存储 仅仅包含形参*/
        List<? super Function> funcWithParams = new ArrayList<>();
        /*存储 无形参和返回值*/
        List<? super Function> funcNoParamsNoResult = new ArrayList<>();
        /*存储 拥有返回值和形参*/
        List<? super Function> funcWithParamsAndResult = new ArrayList<>();

        mFuncMap = new HashMap<>();
        mFuncMap.put(TYPE_WITH_PARAMS_ONLY, funcWithParams);
        mFuncMap.put(TYPE_WITH_RESULT_ONLY, funcWithResult);
        mFuncMap.put(TYPE_NO_PARAMS_NO_RESULT, funcNoParamsNoResult);
        mFuncMap.put(TYPE_WITH_PARAMS_AND_RESULT, funcWithParamsAndResult);
    }

    private static FunctionManager mFunctionManager;

    /**
     * 多线程安全单例
     *
     * @return FunctionManager
     */
    public static FunctionManager getInstance() {
        if (null == mFunctionManager) {
            synchronized (FunctionManager.class) {
                if (null == mFunctionManager) {
                    mFunctionManager = new FunctionManager();
                }
            }
        }
        return mFunctionManager;
    }

    private Map<Integer, List<? super Function>> mFuncMap;

    /**
     * 根据特定的Type添加对应的Function
     * @param type
     * @param funcName
     * @param function
     */
    public void addFunc(@Type int type, @NonNull String funcName, @NonNull Function function) {
        if (TextUtils.isEmpty(funcName) || null == function) {
            return;
        }
        List<? super Function> funcWithResult = mFuncMap.get(type);
        if (funcWithResult.contains(function))
            return;
        funcWithResult.add(function);
    }

    /**
     * 根据特定的Type移除对应的Function
     *  返回1:移除成功  0:失败  -1:无效
     * @param type
     * @param function
     */
    public int removeFunc(@Type int type, @NonNull Function function){
        List<? super Function> funcWithResult = mFuncMap.get(type);
        if (funcWithResult.contains(function))
            return -1;
        return funcWithResult.remove(function) ? 1 : 0;
    }

    /**
     * 调用无形参 有返回值的方法
     * @param funcName 方法名
     * @param <Result> 返回值类型
     * @return
     */
    public <Result> Result invokeFuncWithResult(@NonNull String funcName) {
        /*filter invalid tag*/
        if (TextUtils.isEmpty(funcName))
            return null;
        List<? super Function> funcList = mFuncMap.get(TYPE_WITH_RESULT_ONLY);

        /*inner filter invalid tag*/
        if (null == funcList || funcList.size() <= 0)
            return null;

        FunctionWithResultOnly func;
        for (Object obj : funcList) {
            func = ((FunctionWithResultOnly) obj);
            if (funcName.equals(func.mFunctionName)) {
                return (Result)func.invoke();
            }
        }

        return null;
    }

    /**
     * 调用有形参 有返回值的方法
     * @param funcName 方法名
     * @return
     */
    public <Params, Result> Result invokeFuncWithParamsAndResult(@NonNull String funcName, Params params) {
        /*filter invalid tag*/
        if (TextUtils.isEmpty(funcName))
            return null;
        List<? super Function> funcList = mFuncMap.get(TYPE_WITH_PARAMS_AND_RESULT);

        /*inner filter invalid tag*/
        if (null == funcList || funcList.size() <= 0)
            return null;

        FunctionWithParamsAndResult func;
        for (Object obj : funcList) {
            func = ((FunctionWithParamsAndResult) obj);
            if (funcName.equals(func.mFunctionName)) {
                return (Result) func.invoke(params);
            }
        }
        return null;
    }

    /**
     * 调用有形参 无返回值的方法
     * @param funcName 方法名
     * @return
     */
    public <Params> void invokeFuncWithParams(@NonNull String funcName, Params params) {
        /*filter invalid tag*/
        if (TextUtils.isEmpty(funcName))
            return;
        List<? super Function> funcList = mFuncMap.get(TYPE_WITH_PARAMS_ONLY);

        /*inner filter invalid tag*/
        if (null == funcList || funcList.size() <= 0)
            return;

        FunctionWithParamsOnly func;
        for (Object obj : funcList) {
            func = ((FunctionWithParamsOnly) obj);
            if (funcName.equals(func.mFunctionName)) {
                func.invoke(params);
            }
        }
    }

    /**
     * 调用无形参 无返回值的方法
     * @param funcName 方法名
     * @return
     */
    public void invokeFuncWithParamsAndResult(@NonNull String funcName) {
        /*filter invalid tag*/
        if (TextUtils.isEmpty(funcName))
            return;
        List<? super Function> funcList = mFuncMap.get(TYPE_NO_PARAMS_NO_RESULT);

        /*inner filter invalid tag*/
        if (null == funcList || funcList.size() <= 0)
            return;

        FunctionNoParamsNoResult func;
        for (Object obj : funcList) {
            func = ((FunctionNoParamsNoResult) obj);
            if (funcName.equals(func.mFunctionName)) {
                func.invoke();
            }
        }
    }
}