超越模板方法模式,模板接口方式,来自于Gson例子

模板方法模式:https://blog.csdn.net/dengjili/article/details/79631472

类ObjectNavigator

/*
 * Copyright (C) 2008 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.gson;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.Collection;

/**
 * Provides ability to apply a visitor to an object and all of its fields recursively.
 *
 * @author Inderjeet Singh
 * @author Joel Leitch
 */
final class ObjectNavigator {

  public interface Visitor {
    /**
     * This is called before the object navigator starts visiting the current object
     */
    void startVisitingObject(Object node);

    /**
     * This is called after the object navigator finishes visiting the current object
     */
    void endVisitingObject(Object node);

    /**
     * This is called to visit the current object if it is an iterable
     *
     * @param componentType the type of each element of the component
     */
    void visitCollection(@SuppressWarnings("unchecked") Collection collection, Type componentType);

    /**
     * This is called to visit the current object if it is an array
     */
    void visitArray(Object array, Type componentType);

    /**
     * This is called to visit the current object if it is a primitive
     */
    void visitPrimitiveValue(Object obj);

    /**
     * This is called to visit an object field of the current object
     */
    void visitObjectField(Field f, Object obj);

    /**
     * This is called to visit a field of type Collection of the current object
     */
    void visitCollectionField(Field f, Object obj);

    /**
     * This is called to visit an array field of the current object
     */
    void visitArrayField(Field f, Object obj);

    /**
     * This is called to visit a primitive field of the current object
     */
    void visitPrimitiveField(Field f, Object obj);

    /**
     * This is called to visit an enum object
     */
    public void visitEnum(Object obj, Type objType);

    /**
     * This is called to visit an object using a custom handler
     * @return true if a custom handler exists, false otherwise
     */
    public boolean visitUsingCustomHandler(Object obj, Type objType);
  }

  private final ExclusionStrategy exclusionStrategy;
  private final MemoryRefStack<Object> ancestors;
  private final Object obj;
  private final Type objType;

  /**
   * @param obj The object being navigated
   * @param objType The (fully genericized) type of the object being navigated
   * @param exclusionStrategy the concrete strategy object to be used to
   *        filter out fields of an object.
   */
  ObjectNavigator(Object obj, Type objType, ExclusionStrategy exclusionStrategy,
      MemoryRefStack<Object> ancestors) {
    Preconditions.checkNotNull(exclusionStrategy);
    Preconditions.checkNotNull(ancestors);

    this.obj = obj;
    this.objType = objType;
    this.exclusionStrategy = exclusionStrategy;
    this.ancestors = ancestors;
  }

  /**
   * Navigate all the fields of the specified object.
   * If a field is null, it does not get visited.
   */
  @SuppressWarnings("unchecked")
  public void accept(Visitor visitor) {
    if (obj == null) {
      return;
    }
    TypeInfo<?> objTypeInfo = new TypeInfo<Object>(objType);
    if (exclusionStrategy.shouldSkipClass(objTypeInfo.getTopLevelClass())) {
      return;
    }

    if (ancestors.contains(obj)) {
      throw new IllegalStateException("Circular reference found: " + obj);
    }
    ancestors.push(obj);

    try {
      if (isCollectionOrArray(objTypeInfo)) {
        if (objTypeInfo.isArray()) {
          visitor.visitArray(obj, objType);
        } else { // must be a collection
          visitor.visitCollection((Collection<?>)obj, objType);
        }
      } else if (objTypeInfo.getTopLevelClass().isEnum()) {
        visitor.visitEnum(obj, objType);
      } else if (objTypeInfo.isPrimitiveOrStringAndNotAnArray()) {
        visitor.visitPrimitiveValue(obj);
      } else {
        if (!visitor.visitUsingCustomHandler(obj, objType)) {
          visitor.startVisitingObject(obj);
          // For all classes in the inheritance hierarchy (including the current class),
          // visit all fields
          for (Class<?> curr = objTypeInfo.getTopLevelClass();
              curr != null && !curr.equals(Object.class); curr = curr.getSuperclass()) {
            if (!curr.isSynthetic()) {
              navigateClassFields(obj, curr, visitor);
            }
          }
          visitor.endVisitingObject(obj);
        }
      }
    } finally {
      ancestors.pop();
    }
  }

  private void navigateClassFields(Object obj, Class<?> clazz, Visitor visitor) {
    Field[] fields = clazz.getDeclaredFields();
    AccessibleObject.setAccessible(fields, true);
    for (Field f : fields) {
      TypeInfo<?> fieldTypeInfo = new TypeInfo<Object>(f.getType());
      if (exclusionStrategy.shouldSkipField(f)) {
        continue; // skip
      } else if (isCollectionOrArray(fieldTypeInfo)) {
        if (fieldTypeInfo.isArray()) {
          visitor.visitArrayField(f, obj);
        } else { // must be Collection
          visitor.visitCollectionField(f, obj);
        }
      } else if (fieldTypeInfo.isPrimitiveOrStringAndNotAnArray()) {
        visitor.visitPrimitiveField(f, obj);
      } else {
        visitor.visitObjectField(f, obj);
      }
    }
  }

  private static boolean isCollectionOrArray(TypeInfo<?> typeInfo) {
    return Collection.class.isAssignableFrom(typeInfo.getTopLevelClass()) || typeInfo.isArray();
  }

  @SuppressWarnings("unchecked")
  private static final Class[] PRIMITIVE_TYPES = { int.class, long.class, short.class, float.class,
      double.class, byte.class, boolean.class, Integer.class, Long.class, Short.class, Float.class,
      Double.class, Byte.class, Boolean.class };

  @SuppressWarnings("unchecked")
  static boolean isPrimitiveOrString(Object target) {
    if (target instanceof String) {
      return true;
    }
    Class<?> classOfPrimitive = target.getClass();
    for (Class standardPrimitive : PRIMITIVE_TYPES) {
      if (standardPrimitive.isAssignableFrom(classOfPrimitive)) {
        return true;
      }
    }
    return false;
  }
}

代码解析

定义内部接口
这里写图片描述

定义模板方法,直接调用定义的接口方法
这里写图片描述

子类实现这个接口,到达模板方法的目的,将细节延迟到子类
这里写图片描述

优点

这种方式是通过组合方式,达到目的,而模板方法模式是通过继承方式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值