Adapter 设计模式

本篇对应《图解设计模式》第二章。

适配器模式就是“把一个接口转换成另外一个接口”。


Samsung SD Adapter for microSD

比如我们要实现一个 TF (microSD) 卡转 SD 卡适配器。

定义 SdCard 接口。

public interface SdCard {
    /**
     * read data from SD card
     * @return
     */
    public String readSd();

    /**
     * write data to SD card
     * @param data
     * @return
     */
    public Boolean writeSd(String data);
}

定义 TfCard 接口。

public interface TfCard {
    /**
     * read data from TF card
     * @return
     */
    public String readTf();

    /**
     * write data to TF card
     * @param data
     * @return
     */
    public Boolean writeTf(String data);
}

实现 SdCardAdapter。

public class SdCardAdapter implements SdCard {
    /**
     * TF card
     */
    private TfCard tfCard;

    /**
     * read data from TF card (using SD card adpater)
     */
    @Override
    public String readSd() {
        return tfCard.readTf();
    }

    /**
     * write data to TF card (using SD card adpater)
     */
    @Override
    public Boolean writeSd(String data) {
        return tfCard.writeTf(data);
    }
}

参考:

https://book.douban.com/subject/26933281/

https://www.runoob.com/design-pattern/adapter-pattern.html

80 total views, no views today

Iterator 设计模式

本篇对应《图解设计模式》第一章。

我觉得 Iterator 设计模式是一个很成功的设计模式,对集合遍历问题进行了抽象。

具体到 Java 语言来讲,Iterator 设计模式是 Collections Framework 的一部分。


Iterator 接口

package java.util;

import java.util.function.Consumer;

/**
 * An iterator over a collection.  {@code Iterator} takes the place of
 * {@link Enumeration} in the Java Collections Framework.  Iterators
 * differ from enumerations in two ways:
 *
 * <ul>
 *      <li> Iterators allow the caller to remove elements from the
 *           underlying collection during the iteration with well-defined
 *           semantics.
 *      <li> Method names have been improved.
 * </ul>
 *
 * <p>This interface is a member of the
 * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
 * Java Collections Framework</a>.
 *
 * @apiNote
 * An {@link Enumeration} can be converted into an {@code Iterator} by
 * using the {@link Enumeration#asIterator} method.
 *
 * @param <E> the type of elements returned by this iterator
 *
 * @author  Josh Bloch
 * @see Collection
 * @see ListIterator
 * @see Iterable
 * @since 1.2
 */
public interface Iterator<E> {
    /**
     * Returns {@code true} if the iteration has more elements.
     * (In other words, returns {@code true} if {@link #next} would
     * return an element rather than throwing an exception.)
     *
     * @return {@code true} if the iteration has more elements
     */
    boolean hasNext();

    /**
     * Returns the next element in the iteration.
     *
     * @return the next element in the iteration
     * @throws NoSuchElementException if the iteration has no more elements
     */
    E next();

    /**
     * Removes from the underlying collection the last element returned
     * by this iterator (optional operation).  This method can be called
     * only once per call to {@link #next}.
     * <p>
     * The behavior of an iterator is unspecified if the underlying collection
     * is modified while the iteration is in progress in any way other than by
     * calling this method, unless an overriding class has specified a
     * concurrent modification policy.
     * <p>
     * The behavior of an iterator is unspecified if this method is called
     * after a call to the {@link #forEachRemaining forEachRemaining} method.
     *
     * @implSpec
     * The default implementation throws an instance of
     * {@link UnsupportedOperationException} and performs no other action.
     *
     * @throws UnsupportedOperationException if the {@code remove}
     *         operation is not supported by this iterator
     *
     * @throws IllegalStateException if the {@code next} method has not
     *         yet been called, or the {@code remove} method has already
     *         been called after the last call to the {@code next}
     *         method
     */
    default void remove() {
        throw new UnsupportedOperationException("remove");
    }

    /**
     * Performs the given action for each remaining element until all elements
     * have been processed or the action throws an exception.  Actions are
     * performed in the order of iteration, if that order is specified.
     * Exceptions thrown by the action are relayed to the caller.
     * <p>
     * The behavior of an iterator is unspecified if the action modifies the
     * collection in any way (even by calling the {@link #remove remove} method
     * or other mutator methods of {@code Iterator} subtypes),
     * unless an overriding class has specified a concurrent modification policy.
     * <p>
     * Subsequent behavior of an iterator is unspecified if the action throws an
     * exception.
     *
     * @implSpec
     * <p>The default implementation behaves as if:
     * <pre>{@code
     *     while (hasNext())
     *         action.accept(next());
     * }</pre>
     *
     * @param action The action to be performed for each element
     * @throws NullPointerException if the specified action is null
     * @since 1.8
     */
    default void forEachRemaining(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        while (hasNext())
            action.accept(next());
    }
}

Iterable 接口

package java.lang;

import java.util.Iterator;
import java.util.Objects;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.Consumer;

/**
 * Implementing this interface allows an object to be the target of the enhanced
 * {@code for} statement (sometimes called the "for-each loop" statement).
 *
 * @param <T> the type of elements returned by the iterator
 *
 * @since 1.5
 * @jls 14.14.2 The enhanced {@code for} statement
 */
public interface Iterable<T> {
    /**
     * Returns an iterator over elements of type {@code T}.
     *
     * @return an Iterator.
     */
    Iterator<T> iterator();

    /**
     * Performs the given action for each element of the {@code Iterable}
     * until all elements have been processed or the action throws an
     * exception.  Actions are performed in the order of iteration, if that
     * order is specified.  Exceptions thrown by the action are relayed to the
     * caller.
     * <p>
     * The behavior of this method is unspecified if the action performs
     * side-effects that modify the underlying source of elements, unless an
     * overriding class has specified a concurrent modification policy.
     *
     * @implSpec
     * <p>The default implementation behaves as if:
     * <pre>{@code
     *     for (T t : this)
     *         action.accept(t);
     * }</pre>
     *
     * @param action The action to be performed for each element
     * @throws NullPointerException if the specified action is null
     * @since 1.8
     */
    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }

    /**
     * Creates a {@link Spliterator} over the elements described by this
     * {@code Iterable}.
     *
     * @implSpec
     * The default implementation creates an
     * <em><a href="../util/Spliterator.html#binding">early-binding</a></em>
     * spliterator from the iterable's {@code Iterator}.  The spliterator
     * inherits the <em>fail-fast</em> properties of the iterable's iterator.
     *
     * @implNote
     * The default implementation should usually be overridden.  The
     * spliterator returned by the default implementation has poor splitting
     * capabilities, is unsized, and does not report any spliterator
     * characteristics. Implementing classes can nearly always provide a
     * better implementation.
     *
     * @return a {@code Spliterator} over the elements described by this
     * {@code Iterable}.
     * @since 1.8
     */
    default Spliterator<T> spliterator() {
        return Spliterators.spliteratorUnknownSize(iterator(), 0);
    }
}

分别使用几种不同的方法对集合进行遍历(都是基于 Iterator 设计模式)。

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

public class Main
{
    public static void main(String[] args) {
        List<String> list = Arrays.asList("Hello", "World", "GoodBye");

        whileLoop(list);

        forLoop(list);

        forInLoop(list);

        forEachLoop(list);
    }

    // while loop, using iterator design pattern
    public static void whileLoop(Iterable iterable) {
        Iterator it = iterable.iterator();
        while(it.hasNext()) {
            System.out.println(it.next());
        }
    }

    // for loop, using iterator design pattern
    public static void forLoop(Iterable iterable) {
        for(Iterator it = iterable.iterator(); it.hasNext(); ) {
            System.out.println(it.next());
        }
    }

    // for/in, based on iterator design pattern
    public static void forInLoop(Iterable iterable) {
        for(Object object : iterable) {
            System.out.println(object);
        }
    }

    // forEach, based on for/in and functional programming
    public static void forEachLoop(Iterable iterable) {
        iterable.forEach(x -> System.out.println(x));
    }
}

参考:

https://book.douban.com/subject/26933281/

https://www.runoob.com/java/collection-iterator.html

https://www.ibm.com/developerworks/cn/java/j-forin.html

https://docs.oracle.com/javase/tutorial/collections/intro/index.html

https://github.com/tanghengzhi/java-design-pattern/tree/master/src/Iterator

363 total views, no views today