zoukankan      html  css  js  c++  java
  • java adapter(适配器)惯用方法

      如果现在有一个Iterable类,你想要添加一种或多种在foreach语句中使用这个类的方法,例如方向迭代,应该怎么做呢? 如果之间继承这个类,并且覆盖iterator()方法,你只能替换现有的方法,而不能实现选择

      一种解决方案是所谓的adapter方法的惯用法,"适配器"部分来自于设计模式,因为你必须提供特定接口以满足foreach语句,当你有一个接口并需要另一个接口时,编写adapter就可以解决问题,这里,希望在默认的前向迭代器的基础上,添加方向迭代器的能力,因此不能使用覆盖,而是添加了一个能够产生Iterable对象的方法,该对象可以用于foreach语句,正如你所见,可以提供多种使用foreach的方式

    package object;
    //: holding/AdapterMethodIdiom.java
    // The "Adapter Method" idiom allows you to use foreach
    // with additional kinds of Iterables.
    import java.util.*;
    
    class ReversibleArrayList<T> extends ArrayList<T> {
      public ReversibleArrayList(Collection<T> c) { super(c); }
      public Iterable<T> reversed() {//返回一个具有反向迭代器的Iterable
        return new Iterable<T>() {
          public Iterator<T> iterator() {
            return new Iterator<T>() {
              int current = size() - 1;
              public boolean hasNext() { return current > -1; }
              public T next() { return get(current--); }
              public void remove() { // Not implemented
                throw new UnsupportedOperationException();
              }
            };
          }
        };
      }
    }    
    
    public class AdapterMethodIdiom {
      public static void main(String[] args) {
        ReversibleArrayList<String> ral =
          new ReversibleArrayList<String>(
            Arrays.asList("To be or not to be".split(" ")));
        // Grabs the ordinary iterator via iterator():
        for(String s : ral)
          System.out.print(s + " ");
        System.out.println();
        // Hand it the Iterable of your choice
        for(String s : ral.reversed())
          System.out.print(s + " ");
      }
    } /* Output:
    To be or not to be
    be to not or be To
    *///:~

       通过这种方法,可以在IterableClass.java的示例中添加两种适配器方法

    package object;
    //: holding/MultiIterableClass.java
    // Adding several Adapter Methods.
    import java.util.*;
    
    public class MultiIterableClass extends IterableClass {
      public Iterable<String> reversed() {
        return new Iterable<String>() {
          public Iterator<String> iterator() {
            return new Iterator<String>() {
              int current = words.length - 1;
              public boolean hasNext() { return current > -1; }
              public String next() { return words[current--]; }
              public void remove() { // Not implemented
                throw new UnsupportedOperationException();
              }
            };
          }
        };
      }    
      public Iterable<String> randomized() {
        return new Iterable<String>() {
          public Iterator<String> iterator() {
            List<String> shuffled =
              new ArrayList<String>(Arrays.asList(words));
            Collections.shuffle(shuffled, new Random(47));////
            return shuffled.iterator();
          }
        };
      }    
      public static void main(String[] args) {
        MultiIterableClass mic = new MultiIterableClass();
        for(String s : mic.reversed())
         System.out.print(s + " ");
        System.out.println();
        for(String s : mic.randomized())
          System.out.print(s + " ");
        System.out.println();
        for(String s : mic)
          System.out.print(s + " ");
      }
    } /* Output:
    banana-shaped. be to Earth the know we how is that And
    is banana-shaped. Earth that how the be And we know to
    And that is how we know the Earth to be banana-shaped.
    *///:~
    Collections方法并没有打乱原来的数组,而是打乱了shuffled中的引用,之所以这样,只是因为,randmize()方法用一个ArrayList将Arrays.asList()结果包装了起来
    如果这个有Arrays.asList()产生的List被直接打乱,那么就会修改底层是数组,就像下面这样;
    package object;
    //: holding/ModifyingArraysAsList.java
    import java.util.*;
    
    public class ModifyingArraysAsList {
      public static void main(String[] args) {
        Random rand = new Random(47);
        Integer[] ia = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
        List<Integer> list1 =
          new ArrayList<Integer>(Arrays.asList(ia));//ia的输出被传给了ArrayList构造器,这将创建一个ia的元素引用的ArrayList
        System.out.println("Before shuffling: " + list1);
        Collections.shuffle(list1, rand);
        System.out.println("After shuffling: " + list1);
        System.out.println("array: " + Arrays.toString(ia));
    
        List<Integer> list2 = Arrays.asList(ia);//lsit2 直接使用Arrays.asList(ia),这样做会直接修改ia的数据
        System.out.println("Before shuffling: " + list2);
        Collections.shuffle(list2, rand);
        System.out.println("After shuffling: " + list2);
        System.out.println("array: " + Arrays.toString(ia));
      }
    } /* Output:
    Before shuffling: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    After shuffling: [4, 6, 3, 1, 8, 7, 2, 5, 10, 9]
    array: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    Before shuffling: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    After shuffling: [9, 1, 6, 3, 7, 2, 5, 10, 4, 8]
    array: [9, 1, 6, 3, 7, 2, 5, 10, 4, 8]
    *///:~

     意识到Arrays.asLIst()产生的对象会使用底层数组作为其物理实现是很重要的,只要你执行的操作会修改这个List,并且你不想原来的数组被修改那么你就应该在另一个容器中创建副本

  • 相关阅读:
    ASP.NET MVC 实现页落网资源分享网站+充值管理+后台管理(4)之业务仓储工厂
    ASP.NET MVC 实现页落网资源分享网站+充值管理+后台管理(3)之创建实体层
    ASP.NET MVC 实现页落网资源分享网站+充值管理+后台管理(2)之创建项目
    ASP.NET MVC 实现页落网资源分享网站+充值管理+后台管理(1)之数据库设计
    ASP.NET MVC 实现页落网资源分享网站+充值管理+后台管理(开篇)
    jQuery验证码发送时间秒递减(刷新存储cookie)
    闲来无事写一个jquery计算器,没有进行封装......
    ASP.NET MVC4.0+EF+LINQ+bui+网站+角色权限管理系统(7)
    <script runat=server>、<%%>和<%#%>的区别
    .net 实现 URL重写,伪静态
  • 原文地址:https://www.cnblogs.com/jiangfeilong/p/10284912.html
Copyright © 2011-2022 走看看