什么是迭代器模式呢?
迭代器模式就是提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示。
理解起来是不是很抽象?我们下面马上举个例子!
很多玩LOL的玩家可能都知道,LOL在中国的联赛LPL联赛。
嗯,这个比赛的参赛俱乐部的管理组织就是大名鼎鼎的中国电子竞技俱乐部联盟(Association of China E-sports)简称ACE联盟。该组织负责国内职业电子竞技战队注册、管理、转会、赛事监督等多方面工作,并颁布职业联赛参赛俱乐部管理办法、职业选手个人行为规范等多个条例。
下面我们来建立一个LPL联系的两支参赛队在ACE的管理和介绍系统。这两支队伍分别是IG战队和WE战队。
我们先来构建一个参赛队员类:
//游戏选手类 public class GamePlayer { //姓名和选手描述 private String name,description; //是否为男性选手 private boolean male; //身价 private float salary; //初始化构造函数 public GamePlayer(String name,String description,boolean male,float salary) { this.name=name; this.description=description; this.male=male; this.salary=salary; } public String getName() { return name; } public String getDescription() { return description; } public float getSalary() { return salary; } public boolean isMale() { return male; } }
再来构建IG战队类
public class IgLolGameTeam { //最大上场队员数 private final static int Max_Players=5; //队员统计 public int numberOfplayer=0; //队员存储数组 private GamePlayer[] gameplayers; //构造函数 public IgLolGameTeam() { gameplayers=new GamePlayer[Max_Players] ; addPlayer("上单_957","A级",true,900000f); addPlayer("打野_Condi","A级",true,800000f); addPlayer("中单_xiye","S级",true,1500000f); addPlayer("AD_MyStic","S级",true,130000f); addPlayer("辅助_Zero","A级",true,800000f); } //添加队员函数 private void addPlayer(String name, String description, boolean male,float salary) { GamePlayer gameplayer = new GamePlayer(name, description, male, salary); if(numberOfplayer>=Max_Players) { System.err.println("sorry,menu is full!can not add another item"); }else{ gameplayers[numberOfplayer]=gameplayer; numberOfplayer++; } } //获取所有上场队员 public GamePlayer[] getGamePlayers() { return gameplayers; } }
WE战队类
public class WeLolGameTeam { //队员存储数组 private ArrayList<GamePlayer> gameplayers; //构造函数 public WeLolGameTeam() { gameplayers = new ArrayList<GamePlayer>(); addPlayer("上单_Duke","S级",true,2000000f); addPlayer("打野_Kid","A级",true,1000000f); addPlayer("中单_Rookie","S级",true,1500000f); addPlayer("AD_Rain","A级",true,90000f); addPlayer("辅助_Tabe","A级",true,900000f); } //添加队员函数 private void addPlayer(String name, String description, boolean male,float salary) { GamePlayer gameplayer = new GamePlayer(name, description, male, salary); gameplayers.add(gameplayer); } //获取所有上场队员 public ArrayList<GamePlayer> getGamePlayers() { return gameplayers; } }
我们可以看到,由于每个战队的管理风格不同,所以各战队间的存储队员的数据结构也各不相同,WE用的是动态数组,而IG战队使用的就是一般的数组。
下面我们来构建ACE联盟类:
public class AssociationOfChinaEsports { //战队 private IgLolGameTeam mIgLolGameTeam; private WeLolGameTeam mWeLolGameTeam; //队员存储 private ArrayList<GamePlayer> gameplayers_we; private GamePlayer[] gameplayers_ig; //构造函数 public AssociationOfChinaEsports() { //战队初始化 mWeLolGameTeam = new WeLolGameTeam(); gameplayers_we = mWeLolGameTeam.getGamePlayers(); mIgLolGameTeam = new IgLolGameTeam(); gameplayers_ig = mIgLolGameTeam.getGamePlayers(); } //打印队员信息 public void printPlayer() { GamePlayer gameplayer; System.out.println("IG战队队员:"); for (int i = 0, len = gameplayers_we.size(); i < len; i++) { gameplayer = gameplayers_we.get(i); System.out.println(gameplayer.getName() + "***" +gameplayer.isMale() + "***" + gameplayer.getDescription()); } System.out.println("========================================="); System.out.println("WE战队队员:"); for (int i = 0, len = mIgLolGameTeam.numberOfplayer; i < len; i++) { gameplayer = gameplayers_ig[i]; System.out.println(gameplayer.getName() + "***" +gameplayer.isMale() + "***" + gameplayer.getDescription()); } } } 下面我们用测试函数输出一下,我们每个队员的信息
public class MainTest { public static void main(String[] args) { AssociationOfChinaEsports mAssociationOfChinaEsports=new AssociationOfChinaEsports(); mAssociationOfChinaEsports.printPlayer(); } }
在这个例子中我们可能会发现一些问题:由于各个战队之间的管理不同(存储),导致在ACE里不能进行统一的处理,这样会过多的暴露各个战队的机密信息,比如各个选手的工资水平,而这些信息对于每个战队来讲都是绝密的。
那我们应该怎么办呢?这里就应该使用迭代器模式去处理这个问题了。
首先,我们先定义一个迭代器接口
//迭代器接口 public interface Iterator { //判断是否有下一个队员 public boolean hasNext(); //返回下一个队员 public Object next(); }
然后重新构建两个战队的类,并用内部类的形式实现迭代器
IG:
public class IgLolGameTeam { //最大上场队员数 private final static int Max_Players=5; //队员统计 public int numberOfplayer=0; //队员存储数组 private GamePlayer[] gameplayers; //构造函数 public IgLolGameTeam() { gameplayers=new GamePlayer[Max_Players] ; addPlayer("上单_957","A级",true,900000f); addPlayer("打野_Condi","A级",true,800000f); addPlayer("中单_xiye","S级",true,1500000f); addPlayer("AD_MyStic","S级",true,130000f); addPlayer("辅助_Zero","A级",true,800000f); } //添加队员函数 private void addPlayer(String name, String description, boolean male,float salary) { GamePlayer gameplayer = new GamePlayer(name, description, male, salary); if(numberOfplayer>=Max_Players) { System.err.println("sorry,menu is full!can not add another item"); }else{ gameplayers[numberOfplayer]=gameplayer; numberOfplayer++; } } //获取迭代器 public Iterator getIterator() { return new IgLolGameTeamIterator() ; } //实现迭代器 class IgLolGameTeamIterator implements Iterator { private int position; public IgLolGameTeamIterator() { position = 0; } @Override public boolean hasNext() { // TODO Auto-generated method stub if (position < numberOfplayer) { return true; } return false; } @Override public Object next() { // TODO Auto-generated method stub GamePlayer gameplayer_sub = gameplayers[position]; position++; return gameplayer_sub; } }; } WE
public class WeLolGameTeam { //队员存储数组 private ArrayList<GamePlayer> gameplayers; //构造函数 public WeLolGameTeam() { gameplayers = new ArrayList<GamePlayer>(); addPlayer("上单_Duke","S级",true,2000000f); addPlayer("打野_Kid","A级",true,1000000f); addPlayer("中单_Rookie","S级",true,1500000f); addPlayer("AD_Rain","A级",true,90000f); addPlayer("辅助_Tabe","A级",true,900000f); } //添加队员函数 private void addPlayer(String name, String description, boolean male,float salary) { GamePlayer gameplayer = new GamePlayer(name, description, male, salary); gameplayers.add(gameplayer); } //获取迭代器 public Iterator getIterator() { return new WeLolGameTeamIterator(); } //实现迭代器 class WeLolGameTeamIterator implements Iterator { private int position=0; public WeLolGameTeamIterator() { position=0; } @Override public boolean hasNext() { // TODO Auto-generated method stub if(position<gameplayers.size()) { return true; } return false; } @Override public Object next() { // TODO Auto-generated method stub GamePlayer gameplayer_sub =gameplayers.get(position); position++; return gameplayer_sub; }}; }
然后是ACE联盟来处理这些迭代器
public class AssociationOfChinaEsports { private ArrayList<Iterator> iterators=new ArrayList<Iterator>(); public AssociationOfChinaEsports() { } //添加迭代器 public void addIterator(Iterator iterator) { iterators.add(iterator); } //打印队员信息 public void printMenu() { Iterator iterator; GamePlayer menuItem; for (int i = 0, len = iterators.size(); i < len; i++) { iterator = iterators.get(i); System.out.println("战队介绍:"); while(iterator.hasNext()) { menuItem=(GamePlayer) iterator.next(); System.out.println(menuItem.getName() + "***" +menuItem.isMale()+"***" + menuItem.getDescription()); } System.out.println("============================================="); } } } 最后我们来测试一下
public class MainTest { public static void main(String[] args) { AssociationOfChinaEsports mAssociationOfChinaEsports=new AssociationOfChinaEsports(); IgLolGameTeam mIgLolGameTeam = new IgLolGameTeam(); WeLolGameTeam mWeLolGameTeam = new WeLolGameTeam(); mAssociationOfChinaEsports.addIterator(mIgLolGameTeam.getIterator()); mAssociationOfChinaEsports.addIterator(mWeLolGameTeam.getIterator()); mAssociationOfChinaEsports.printMenu(); } }
这回我们可以清晰的看见,在ACE联盟类中,每个战队都没有暴露他们的细节,这就是迭代器模式的有点!
迭代器模式的优点有: 1.简化了遍历方式,用户用起来简单了。 2.可以进行多种遍历方式的使用,方便了对集合的遍历。 3.封装性良好,只需要得到迭代器遍历,而对于遍历算法则不用去关心,并且更好的封装了内部的信息细节。 迭代器模式的缺点: 1.对于比较简单的遍历,使用较为繁琐。
迭代器的适用场景:
1.对于容器的自定义迭代。
=============================================================
最后为lpl的中国战队加油!在今年的S8世界总决赛中,希望他们能有个好成绩!!