• 设计模式11-迭代器模式与命令模式详解


    1.11-迭代器模式与命令模式详解

    1.11.1.迭代器模式详解

    时长:42min

    11.1.1.迭代器模式的定义

    定义:

      迭代器模式【Iterator Pattern】,又叫游标模式【Cursor Pattern】,它提供一种顺序访问集合/容器

    对象元素的方法,又无须暴露集合内部表示。

    本质:

      抽离集合对象迭代行为到迭代器中,提供一致访问接口。

      属于行为型模式。

    11.1.1.1.迭代器模式在生活中体现

    》寄件迭代分发

    》刷脸检票进站

    11.1.1.2.迭代器模式使用场景

    1.访问一个集合对象的内容而无须暴露它的内部表示【遍历集合元素】

    2.为遍历不同的集合结构提供一个统一的访问接口

    11.1.2.迭代器模式的通用实现

    11.1.2.1.系统类图设计

    11.1.2.2.系统代码实现
    1.顶层聚合容器接口
    package com.wf.iterator.general;
    
    /**
     * @ClassName IAggregate
     * @Description 顶层聚合接口
     * @Author wf
     * @Date 2020/6/19 9:55
     * @Version 1.0
     */
    public interface IAggregate<E> {
        boolean add(E e);
        boolean remove(E e);
        Iterator<E> iterator();
    }
    2.聚合容器实现子类
    package com.wf.iterator.general;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @ClassName ConcreteAggregate
     * @Description 聚合对象子类实现
     * @Author wf
     * @Date 2020/6/19 9:58
     * @Version 1.0
     */
    public class ConcreteAggregate<E> implements IAggregate<E> {
        private List<E> list = new ArrayList<E>();
    
        @Override
        public boolean add(E ele) {
            return this.list.add(ele);
        }
    
        @Override
        public boolean remove(E ele) {
            return this.list.remove(ele);
        }
    
        @Override
        public Iterator<E> iterator() {
            return new ConcreteIterator<E>(this.list);
        }
    }
    3.顶层迭代器接口定义
    package com.wf.iterator.general;
    
    /**
     * @ClassName Iterator
     * @Description 顶层迭代器接口
     * @Author wf
     * @Date 2020/6/19 10:31
     * @Version 1.0
     */
    public interface Iterator<E> {
        boolean hasNext();
        E next();
    }
    4.迭代器具体子类实现
    package com.wf.iterator.general;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @ClassName ConcreteIterator
     * @Description 实现迭代器功能
     * @Author wf
     * @Date 2020/6/19 9:57
     * @Version 1.0
     */
    public class ConcreteIterator<E> implements Iterator<E> {
        private List<E> list = new ArrayList<E>();
        int cursor;
        public ConcreteIterator(List<E> list) {
            this.list = list;
        }
    
        @Override
        public boolean hasNext() {
            return cursor != list.size();
        }
    
        @Override
        public E next() {
            return list.get(cursor++);
        }
    }
    5.测试类
    package com.wf.iterator.general;
    
    
    /**
     * @ClassName Test
     * @Description 测试类
     * @Author wf
     * @Date 2020/6/19 10:01
     * @Version 1.0
     */
    public class Test {
        public static void main(String[] args) {
            //创建一个聚合容器
            IAggregate<String> aggregate = new ConcreteAggregate<String>();
    
            //存储元素
            aggregate.add("one");
            aggregate.add("two");
            aggregate.add("three");
            //获取容器对象迭代器
            Iterator<String> iterator = aggregate.iterator();
            //遍历迭代器
            while (iterator.hasNext()){
                String ele = iterator.next();
                System.out.println(ele);
            }
        }
    }

    测试结果如下:

    11.1.3.迭代器模式应用案例之课程存储容器

    11.1.3.1.代码实现
    1.顶层容器接口
    package com.wf.iterator.demo.course;
    
    /**
     * @ClassName ICourseAggregate
     * @Description 课程类聚合容器
     * @Author wf
     * @Date 2020/6/19 10:42
     * @Version 1.0
     */
    public interface ICourseAggregate {
        boolean add(Course course);
        boolean remove(Course course);
        Iterator<Course> iterator();
    }
    2.容器具体实现子类
    package com.wf.iterator.demo.course;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @ClassName CourseAggregateImpl
     * @Description 课程类聚合容器子类实现
     * @Author wf
     * @Date 2020/6/19 10:48
     * @Version 1.0
     */
    public class CourseAggregateImpl implements ICourseAggregate {
        private List<Course> courseList;
    
        public CourseAggregateImpl() {
            this.courseList = new ArrayList<>();
        }
    
        @Override
        public boolean add(Course course) {
            return this.courseList.add(course);
        }
    
        @Override
        public boolean remove(Course course) {
            return this.courseList.remove(course);
        }
    
        @Override
        public Iterator<Course> iterator() {
            return new IteratorImpl<Course>(courseList);
        }
    }
    3.顶层迭代器接口
    package com.wf.iterator.demo.course;
    
    /**
     * @ClassName Iterator
     * @Description 顶层迭代器接口
     * @Author wf
     * @Date 2020/6/19 10:31
     * @Version 1.0
     */
    public interface Iterator<E> {
        boolean hasNext();
        E next();
    }
    4.迭代器具体实现
    package com.wf.iterator.demo.course;
    
    import java.util.List;
    
    /**
     * @ClassName IteratorImpl
     * @Description 迭代器具体实现
     * @Author wf
     * @Date 2020/6/19 10:44
     * @Version 1.0
     */
    public class IteratorImpl<E> implements Iterator {
        private List<E> list;
        private int cursor;
        private E element;
    
        public IteratorImpl(List<E> list) {
            this.list = list;
        }
    
        @Override
        public boolean hasNext() {
            return cursor != list.size();
        }
    
        @Override
        public Object next() {
            System.out.print("当前位置:"+cursor+ ":");
            element = list.get(cursor++);
            return element;
        }
    }
    5.课程类业务bean
    package com.wf.iterator.demo.course;
    
    /**
     * @ClassName Course
     * @Description 课程类,业务bean
     * @Author wf
     * @Date 2020/6/19 10:40
     * @Version 1.0
     */
    public class Course {
        private String name;
    
        public Course(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    }
    6.测试类
    package com.wf.iterator.demo.course;
    
    /**
     * @ClassName Test
     * @Description 测试类
     * @Author wf
     * @Date 2020/6/19 10:51
     * @Version 1.0
     */
    public class Test {
        public static void main(String[] args) {
            Course java = new Course("Java架构");
            Course javaBase = new Course("Java基础");
            Course design = new Course("设计模式");
            Course ai = new Course("人工智能");
    
            ICourseAggregate aggregate = new CourseAggregateImpl();
            aggregate.add(java);
            aggregate.add(javaBase);
            aggregate.add(design);
            aggregate.add(ai);
    
            System.out.println("===========课程列表==============");
            printCourse(aggregate);
            aggregate.remove(ai);
            System.out.println("===========执行删除操作后的课程列表==============");
            printCourse(aggregate);
    
        }
    
        private static void printCourse(ICourseAggregate aggregate) {
            Iterator<Course> it = aggregate.iterator();
            while(it.hasNext()){
                Course course = it.next();
                System.out.println("《"+course.getName()+"》");
            }
        }
    }

    测试结果如下:

    11.1.3.2.系统类图设计

    11.1.4.迭代器模式在源码中应用 

    11.1.4.1.jdk中定义有迭代器接口

    源码如下所示:

    package java.util;
    
    import java.util.function.Consumer;
    
    /*
     * @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> {
        boolean hasNext();
        E next();
        default void remove() {
            throw new UnsupportedOperationException("remove");
        }
        default void forEachRemaining(Consumer<? super E> action) {
            Objects.requireNonNull(action);
            while (hasNext())
                action.accept(next());
        }
    }
    1.接口实现之ArrayList

    定义内部迭代器实现,如下所示:

    private class Itr implements Iterator<E> {
            int cursor;       // index of next element to return
            int lastRet = -1; // index of last element returned; -1 if no such
            int expectedModCount = modCount;
    
            Itr() {}
    
            public boolean hasNext() {
                return cursor != size;
            }
    
            @SuppressWarnings("unchecked")
            public E next() {
                checkForComodification();
                int i = cursor;
                if (i >= size)
                    throw new NoSuchElementException();
                Object[] elementData = ArrayList.this.elementData;
                if (i >= elementData.length)
                    throw new ConcurrentModificationException();
                cursor = i + 1;
                return (E) elementData[lastRet = i];
            }
    
            public void remove() {
                if (lastRet < 0)
                    throw new IllegalStateException();
                checkForComodification();
    
                try {
                    ArrayList.this.remove(lastRet);
                    cursor = lastRet;
                    lastRet = -1;
                    expectedModCount = modCount;
                } catch (IndexOutOfBoundsException ex) {
                    throw new ConcurrentModificationException();
                }
            }
    
            @Override
            @SuppressWarnings("unchecked")
            public void forEachRemaining(Consumer<? super E> consumer) {
                Objects.requireNonNull(consumer);
                final int size = ArrayList.this.size;
                int i = cursor;
                if (i >= size) {
                    return;
                }
                final Object[] elementData = ArrayList.this.elementData;
                if (i >= elementData.length) {
                    throw new ConcurrentModificationException();
                }
                while (i != size && modCount == expectedModCount) {
                    consumer.accept((E) elementData[i++]);
                }
                // update once at end of iteration to reduce heap write traffic
                cursor = i;
                lastRet = i - 1;
                checkForComodification();
            }
    
            final void checkForComodification() {
                if (modCount != expectedModCount)
                    throw new ConcurrentModificationException();
            }
        }
    2.java整个集合框架继承迭代器接口
    public interface Collection<E> extends Iterable<E> {
    11.1.4.2.jdk中hashMap内迭代器
    abstract class HashIterator {
            Node<K,V> next;        // next entry to return
            Node<K,V> current;     // current entry
            int expectedModCount;  // for fast-fail
            int index;             // current slot
    
            HashIterator() {
                expectedModCount = modCount;
                Node<K,V>[] t = table;
                current = next = null;
                index = 0;
                if (t != null && size > 0) { // advance to first entry
                    do {} while (index < t.length && (next = t[index++]) == null);
                }
            }
    
            public final boolean hasNext() {
                return next != null;
            }
    
            final Node<K,V> nextNode() {
                Node<K,V>[] t;
                Node<K,V> e = next;
                if (modCount != expectedModCount)
                    throw new ConcurrentModificationException();
                if (e == null)
                    throw new NoSuchElementException();
                if ((next = (current = e).next) == null && (t = table) != null) {
                    do {} while (index < t.length && (next = t[index++]) == null);
                }
                return e;
            }
    
            public final void remove() {
                Node<K,V> p = current;
                if (p == null)
                    throw new IllegalStateException();
                if (modCount != expectedModCount)
                    throw new ConcurrentModificationException();
                current = null;
                K key = p.key;
                removeNode(hash(key), key, null, false, false);
                expectedModCount = modCount;
            }
        }
    11.1.4.3.mybatis中DefaultCursor内迭代器
    public class DefaultCursor<T> implements Cursor<T> {
    内部迭代器定义:

    private class CursorIterator implements Iterator<T> {
    
            /**
             * Holder for the next object to be returned
             */
            T object;
    
            /**
             * Index of objects returned using next(), and as such, visible to users.
             */
            int iteratorIndex = -1;
    
            @Override
            public boolean hasNext() {
                if (object == null) {
                    object = fetchNextUsingRowBound();
                }
                return object != null;
            }
    
            @Override
            public T next() {
                // Fill next with object fetched from hasNext()
                T next = object;
    
                if (next == null) {
                    next = fetchNextUsingRowBound();
                }
    
                if (next != null) {
                    object = null;
                    iteratorIndex++;
                    return next;
                }
                throw new NoSuchElementException();
            }
    
            @Override
            public void remove() {
                throw new UnsupportedOperationException("Cannot remove element from Cursor");
            }
        }

    11.1.5.迭代器模式使用总结

    11.1.5.1.优缺点总结

    优点:

      1.多态迭代:为不同的聚合结构提供一致的遍历接口,即一个迭代接口可以访问不同的聚合容器对象。

      2.简化集合对象接口:迭代器模式将集合对象本身应该提供的元素迭代接口抽取到迭代器中,使集合对象无须

    关心具体迭代行为。

      3.元素迭代功能多样化:每个集合对象都可以提供一个或多个不同的迭代器,使得同种元素聚合结构可以有不同的迭代行为

      4.解耦迭代与集合:迭代器模式,封装了具体的迭代算法,迭代算法的变化,不会影响到集合对象的架构。

    缺点:

      对于比较简单的遍历【如数组或有序列表】,使用迭代器遍历反而较为繁琐。

    1.11.2.命令模式详解

    时长:36min

    11.2.1.命令模式的定义

    定义:

      命令模式【Command Pattern】,是对命令的封装。每一个命令都是一个操作:请求的一方发出请求要求执行一个操作;接收

    的一方收到请求,并执行操作。命令模式解耦了请求方接收方,请求方只需请求执行命令,不用关心命令是怎样被接收的,怎样

    被操作及是否被执行。。。等。

    本质:解耦命令请求与处理。

      属于行为型模式。

    11.2.1.1.命令模式在生活中的应用

    》遥控器

    》餐厅点菜单

    11.2.1.2.命令模式的适用场景

    1.现实语义中具备“命令"的操作(如:命令菜单,sell命令。。。)

    2.请求调用者和请求接收者需要解耦,使得调用者和接收者不直接交互。

    3.需要抽象出等待执行的行为,比如:撤销(undo)操作和恢复【redo】等

    4.需要支持命令宏【即命令组合操作】

    11.2.2.命令模式的通用实现

    11.2.2.1.类图设计

    11.2.2.2.代码实现
    1.顶层命令接口及实现
    package com.wf.command.general;
    
    /**
     * @ClassName ICommand
     * @Description 命令顶层接口
     * @Author wf
     * @Date 2020/6/19 14:03
     * @Version 1.0
     */
    public interface ICommand {
        void execute();
    }
    package com.wf.command.general;
    
    /**
     * @ClassName ConcreteCommand
     * @Description 具体命令实现
     * @Author wf
     * @Date 2020/6/19 14:05
     * @Version 1.0
     */
    public class ConcreteCommand implements ICommand {
        private Receiver receiver = new Receiver();
    
    
        @Override
        public void execute() {
            receiver.action();
        }
    }
    2.命令接收者
    package com.wf.command.general;
    
    /**
     * @ClassName Receiver
     * @Description 命令接收方
     * @Author wf
     * @Date 2020/6/19 14:06
     * @Version 1.0
     */
    public class Receiver {
        public void action(){
            System.out.println("根据接收到的命令,执行具体操作");
        }
    }
    3.命令发出者
    package com.wf.command.general;
    
    /**
     * @ClassName Invoker
     * @Description 调用者,命令发出方
     * @Author wf
     * @Date 2020/6/19 14:07
     * @Version 1.0
     */
    public class Invoker {
        private ICommand command;
    
        public Invoker(ICommand command) {
            this.command = command;
        }
    
        public void action(){
            command.execute();
        }
    }
    4.测试类
    package com.wf.command.general;
    
    /**
     * @ClassName Test
     * @Description 测试类
     * @Author wf
     * @Date 2020/6/19 14:10
     * @Version 1.0
     */
    public class Test {
        public static void main(String[] args) {
            ICommand command = new ConcreteCommand();
            //命令发出方,需要传送命令
            Invoker invoker = new Invoker(command);
            invoker.action();
        }
    }

    测试结果:

    11.2.3.命令模式的实现案例之播放器

    11.2.3.1.代码实现
    1.命令接口
    package com.wf.command.demo.player.actions;
    
    /**
     * @ClassName IAction
     * @Description 命令接口
     * @Author wf
     * @Date 2020/6/19 14:28
     * @Version 1.0
     */
    public interface IAction {
        void execute();
    }
    2.4种命令实现
    package com.wf.command.demo.player.actions;
    
    import com.wf.command.demo.player.Player;
    
    /**
     * @ClassName StopAction
     * @Description 停止播放命令
     * @Author wf
     * @Date 2020/6/19 14:31
     * @Version 1.0
     */
    public class StopAction implements IAction {
        private Player player;
    
        public StopAction(Player player) {
            this.player = player;
        }
    
        @Override
        public void execute() {
            player.stop();
        }
    }
    package com.wf.command.demo.player.actions;
    
    import com.wf.command.demo.player.Player;
    
    /**
     * @ClassName SpeedAction
     * @Description 拖动滚动条播放命令
     * @Author wf
     * @Date 2020/6/19 14:31
     * @Version 1.0
     */
    public class SpeedAction implements IAction {
        private Player player;
    
        public SpeedAction(Player player) {
            this.player = player;
        }
    
        @Override
        public void execute() {
            player.speed();
        }
    }
    package com.wf.command.demo.player.actions;
    
    import com.wf.command.demo.player.Player;
    
    /**
     * @ClassName PauseAction
     * @Description 暂停播放命令
     * @Author wf
     * @Date 2020/6/19 14:31
     * @Version 1.0
     */
    public class PauseAction implements IAction {
        private Player player;
    
        public PauseAction(Player player) {
            this.player = player;
        }
    
        @Override
        public void execute() {
            player.pause();
        }
    }
    package com.wf.command.demo.player.actions;
    
    import com.wf.command.demo.player.Player;
    
    /**
     * @ClassName PlayAction
     * @Description 正常播放命令实现
     * @Author wf
     * @Date 2020/6/19 14:29
     * @Version 1.0
     */
    public class PlayAction implements IAction {
        private Player player;
    
        public PlayAction(Player player) {
            this.player = player;
        }
    
        @Override
        public void execute() {
            player.play();
        }
    }
    3.播放器,命令接收者
    package com.wf.command.demo.player;
    
    /**
     * @ClassName Player
     * @Description 播放器,命令接收者
     * @Author wf
     * @Date 2020/6/19 14:25
     * @Version 1.0
     */
    public class Player {
        public void play(){
            System.out.println("正常播放");
        }
        public void speed(){
            System.out.println("拖动滚动条");
        }
        public void stop(){
            System.out.println("停止播放");
        }
        public void pause(){
            System.out.println("暂停播放");
        }
    }
    4.遥控器,命令发出者
    package com.wf.command.demo.player;
    
    import com.wf.command.demo.player.actions.IAction;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @ClassName Controller
     * @Description 遥控器,发出命令
     * @Author wf
     * @Date 2020/6/19 14:35
     * @Version 1.0
     */
    public class Controller {
        private List<IAction> actions = new ArrayList<IAction>();
        public void addAction(IAction action){
            actions.add(action);
        }
        public void batchExecute(){
            for (IAction action : actions) {
                action.execute();
            }
            actions.clear();
        }
    
        public void execute(IAction action){
            action.execute();
        }
    }

    注意:

      这里面引入list成员,用以封装接收并处理多条命令,批量执行。

    5.测试类
    package com.wf.command.demo.player;
    
    import com.wf.command.demo.player.actions.*;
    
    /**
     * @ClassName Test
     * @Description 测试类
     * @Author wf
     * @Date 2020/6/19 14:43
     * @Version 1.0
     */
    public class Test {
        public static void main(String[] args) {
            Player player = new Player();
            Controller controller = new Controller();
            //遥控器,点击正常播放键,播放器接收到命令,开始播放
            controller.execute(new PlayAction(player));
            System.out.println("==========开始组合命令式执行:==============");
            //多条命令批量执行
            IAction pause = new PauseAction(player);
            IAction play = new PlayAction(player);
            IAction stop = new StopAction(player);
            IAction speed = new SpeedAction(player);
    
            controller.addAction(pause);
            controller.addAction(play);
            controller.addAction(stop);
            controller.addAction(speed);
    
            controller.batchExecute();
        }
    }
    测试结果:

    11.2.3.2.系统类图设计

    11.2.4.命令模式在源码中的应用

    11.2.4.1.jdk中Runnable接口
    11.2.4.2.junit中TestCase接口

    11.2.5.命令模式使用总结

    11.2.5.1.优缺点总结

    优点:

      1.通过引入中间件【抽象接口】,解耦命令请求与处理。

      2.扩展性良好,方便添加新的命令

      3.支持组合命令,支持命令队列。

      4.可以在现有命令的基础上,增加额外功能(如:日志记录,结合装饰器模式进行代码优化)

    缺点:

      1.具体命令类有很多

      2.增加了程序复杂性,理解更加困难。

  • 相关阅读:
    windows 挂载windows 共享盘为本地磁盘
    模块
    message 匹配不上grok正则 也会写入到elasticsearch
    【Java】No enclosing instance of type XXX is accessible. Must qualify the allocation with an enclosing instance of type XXX(e.g. x.new A() where x is an instance of XXX).的解决办法
    【Ubuntu】常用软件及其下载地址
    【Java】内存分析
    【Java】利用二维数组进行排版
    【Java】一维数组
    【趣题】用for循环输出菱形
    【趣题】穷举法解决百钱买百鸡
  • 原文地址:https://www.cnblogs.com/wfdespace/p/13162158.html
Copyright © 2020-2023  润新知