定义

菜鸟教程

原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用

大话设计模式

用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象

Glide源码阅读之原型模式【TransitionOptions】【BaseRequestOptions】【RequestBuilder】_原型模式

《Android源码设计模式解析与实践》

Glide源码阅读之原型模式【TransitionOptions】【BaseRequestOptions】【RequestBuilder】_源码_02

特点

最大的特点是:implements Cloneable;但凡实现Cloneable接口的一般都满足原型模式。当然也不排除有其他变种情况,不过目前没有碰到。如果有请留言分享,或者后期我碰到后再补充。

注意事项:

与通过对一个类进行实例化来构造新对象不同的是,原型模式是通过拷贝一个现有对象生成新对象的。浅拷贝实现 Cloneable,重写,深拷贝是通过实现 Serializable 读取二进制流。

使用场景

  1. 简历模板
  2. 历史文档修改记录(比如:飞书、腾讯等在线编辑文档)

浅拷贝、深拷贝

浅拷贝

被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用都仍然指向原来的对象。

深拷贝

把引用对象的变量指向复制过的新对象,而不是原有的被引用的对象

Glide原型模式应用

包路径:com.bumptech.glide.TransitionOptions

/**
 * A base class for setting a transition to use on a resource when a load completes.
 *
 * @param <CHILD> The implementation of this class to return to chain methods.
 * @param <TranscodeType> The type of resource that will be animated.
 */
public abstract class TransitionOptions<
        CHILD extends TransitionOptions<CHILD, TranscodeType>, TranscodeType>
    implements Cloneable {
  private TransitionFactory<? super TranscodeType> transitionFactory = NoTransition.getFactory();

  /**
   * Removes any existing animation put on the builder. Will be overridden by subsequent calls that
   * put an animation.
   *
   * @return This request builder.
   */
  @NonNull
  public final CHILD dontTransition() {
    return transition(NoTransition.getFactory());
  }

  /**
   * Sets an {@link android.view.animation.Animation} to run on the wrapped target when an resource
   * load finishes. Will only be run if the resource was loaded asynchronously (i.e. was not in the
   * memory cache).
   *
   * @param viewAnimationId The resource id of the {@link android.view.animation} to use as the
   *     transition.
   * @return This request builder.
   */
  @NonNull
  public final CHILD transition(int viewAnimationId) {
    return transition(new ViewAnimationFactory<>(viewAnimationId));
  }

  /**
   * Sets an animator to run a {@link android.view.ViewPropertyAnimator} on a view that the target
   * may be wrapping when a resource load finishes. Will only be run if the load was loaded
   * asynchronously (i.e. was not in the memory cache).
   *
   * @param animator The {@link com.bumptech.glide.request.transition.ViewPropertyTransition
   *     .Animator} to run.
   * @return This request builder.
   */
  @NonNull
  public final CHILD transition(@NonNull ViewPropertyTransition.Animator animator) {
    return transition(new ViewPropertyAnimationFactory<>(animator));
  }

  /**
   * Uses the given {@link TransitionFactory} to build a {@link
   * com.bumptech.glide.request.transition.Transition} for each request started with these {@code
   * TransitionOptions}.
   *
   * @return This request builder.
   */
  @NonNull
  public final CHILD transition(
      @NonNull TransitionFactory<? super TranscodeType> transitionFactory) {
    this.transitionFactory = Preconditions.checkNotNull(transitionFactory);
    return self();
  }

  @SuppressWarnings({
    // cast to CHILD is safe given the generic argument represents the object's runtime class
    "unchecked",
    // CHILD is the correct class name.
    "PMD.CloneMethodReturnTypeMustMatchClassName",
    // we don't want to throw to be user friendly
    "PMD.CloneThrowsCloneNotSupportedException"
  })
  @Override
  public final CHILD clone() {
    try {
      return (CHILD) super.clone();
    } catch (CloneNotSupportedException e) {
      throw new RuntimeException(e);
    }
  }

  final TransitionFactory<? super TranscodeType> getTransitionFactory() {
    return transitionFactory;
  }

  @SuppressWarnings("unchecked")
  private CHILD self() {
    return (CHILD) this;
  }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.

被RequestBuilder调用,同时RequestBuilder也是原型模式,两者结合正好说明浅拷贝和深拷贝。TransitionOptions属于浅拷贝那种
RequestBuilder调用了TransitionOptions的clone()属于深拷贝那种。当然深浅拷贝取舍也是根据实际业务场景设定的。

/**
 * A generic class that can handle setting options and staring loads for generic resource types.
 *
 * @param <TranscodeType> The type of resource that will be delivered to the {@link
 *     com.bumptech.glide.request.target.Target}.
 */
// Public API.
@SuppressWarnings({"unused", "WeakerAccess"})
public class RequestBuilder<TranscodeType> extends BaseRequestOptions<RequestBuilder<TranscodeType>>
    implements Cloneable, ModelTypes<RequestBuilder<TranscodeType>> {
  。。。
   @NonNull
  @SuppressWarnings("unchecked")
  private TransitionOptions<?, ? super TranscodeType> transitionOptions;
  /**
   * Returns a copy of this request builder with all of the options put so far on this builder.
   *
   * <p>This method returns a "deep" copy in that all non-immutable arguments are copied such that
   * changes to one builder will not affect the other builder. However, in addition to immutable
   * arguments, the current model is not copied so changes to the model will affect both builders.
   */
  @SuppressWarnings({
    // we don't want to throw to be user friendly
    "PMD.CloneThrowsCloneNotSupportedException"
  })
  @CheckResult
  @Override
  public RequestBuilder<TranscodeType> clone() {
    RequestBuilder<TranscodeType> result = super.clone();
    result.transitionOptions = result.transitionOptions.clone();
    if (result.requestListeners != null) {
      result.requestListeners = new ArrayList<>(result.requestListeners);
    }
    if (result.thumbnailBuilder != null) {
      result.thumbnailBuilder = result.thumbnailBuilder.clone();
    }
    if (result.errorBuilder != null) {
      result.errorBuilder = result.errorBuilder.clone();
    }
    return result;
  }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.

再补充一个BaseRequestOptions

/**
 * A base object to allow method sharing between {@link RequestOptions} and {@link
 * com.bumptech.glide.RequestBuilder}.
 *
 * <p>This class is not meant for general use and may change at any time.
 *
 * @param <T> The particular child implementation
 */
@SuppressWarnings({"PMD.UseUtilityClass", "unused"})
public abstract class BaseRequestOptions<T extends BaseRequestOptions<T>> implements Cloneable {
  private static final int UNSET = -1;
  private static final int SIZE_MULTIPLIER = 1 << 1;
  。。。
  
  /**
   * Returns a copy of this request builder with all of the options put so far on this builder.
   *
   * <p>This method returns a "deep" copy in that all non-immutable arguments are copied such that
   * changes to one builder will not affect the other builder. However, in addition to immutable
   * arguments, the current model is not copied copied so changes to the model will affect both
   * builders.
   *
   * <p>Even if this object was locked, the cloned object returned from this method will not be
   * locked.
   */
  @SuppressWarnings({
    "unchecked",
    // we don't want to throw to be user friendly
    "PMD.CloneThrowsCloneNotSupportedException",
    // The types we're using here do this automatically.
    "PMD.CloneMethodReturnTypeMustMatchClassName"
  })
  @CheckResult
  @Override
  public T clone() {
    try {
      BaseRequestOptions<?> result = (BaseRequestOptions<?>) super.clone();
      result.options = new Options();
      result.options.putAll(options);
      result.transformations = new CachedHashCodeArrayMap<>();
      result.transformations.putAll(transformations);
      result.isLocked = false;
      result.isAutoCloneEnabled = false;
      return (T) result;
    } catch (CloneNotSupportedException e) {
      throw new RuntimeException(e);
    }
  }
。。。。
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.

总结

具体的业务上和功能上的介绍就免了,如果有兴趣可以自行翻译。本文介绍的是原型模式的结构以及深浅拷贝的说明。聚焦设计模式解析,争取读完一个模式解析即可在项目上进行应用。


下载地址:

 https://pan.baidu.com/s/1kFAGbsFIk3dDR64NwM5y2A?pwd=csdn