设计模式-迭代器模式(Iterator)

迭代器模式如何理解,不暴露集合底层表现形式的情况下遍历集合中多有的元素,然而在先生世界中,譬如你出去旅游,你要参观主要旅游景点,可是你到达目的地后,你可能要发较多的时间去找如何到达你目的地的地方,你可能会 找当地导游给你进行内容详细接受,你可以能使用 手机导航,或者使用自由行走 模式。走到哪算到哪。其实这就是由这个景区提供给你的集合迭代器。而这模型在 Java 代码中非常常见。许多框架和库使用它来提供遍历其集合的标准方法。在java中使用的有:

java.util.Iterator(以及 java.util.Scanner)的所有实现。

java.util.Enumeration 的所有实现。

下面举一个例子:、

迭代社交网络配置文件

在此示例中,迭代器模式用于检查远程社交网络集合的社交配置文件,而不向客户端代码公开任何通信详细信息。

public class Profile {
	 private String name;
	    private String email;
	    private Map<String, List<String>> contacts = new HashMap<>();

	    public Profile(String email, String name, String... contacts) {
	        this.email = email;
	        this.name = name;

	        // Parse contact list from a set of "friend:email@gmail.com" pairs.
	        for (String contact : contacts) {
	            String[] parts = contact.split(":");
	            String contactType = "friend", contactEmail;
	            if (parts.length == 1) {
	                contactEmail = parts[0];
	            }
	            else {
	                contactType = parts[0];
	                contactEmail = parts[1];
	            }
	            if (!this.contacts.containsKey(contactType)) {
	                this.contacts.put(contactType, new ArrayList<>());
	            }
	            this.contacts.get(contactType).add(contactEmail);
	        }
	    }

	    public String getEmail() {
	        return email;
	    }

	    public String getName() {
	        return name;
	    }

	    public List<String> getContacts(String contactType) {
	        if (!this.contacts.containsKey(contactType)) {
	            this.contacts.put(contactType, new ArrayList<>());
	        }
	        return contacts.get(contactType);
	    }
}

定义迭代器接口:

public interface ProfileIterator {
	boolean hasNext();
	Profile getNext();
	void reset();
}

public interface SocialNetwork {
	
	 ProfileIterator createFriendsIterator(String profileEmail);

     ProfileIterator createCoworkersIterator(String profileEmail);
}

入口:

public class SocialSpammer {
    public SocialNetwork network;
    public ProfileIterator iterator;

    public SocialSpammer(SocialNetwork network) {
        this.network = network;
    }

    public void sendSpamToFriends(String profileEmail, String message) {
        System.out.println("\nIterating over friends...\n");
        iterator = network.createFriendsIterator(profileEmail);
        while (iterator.hasNext()) {
            Profile profile = iterator.getNext();
            sendMessage(profile.getEmail(), message);
        }
    }

    public void sendSpamToCoworkers(String profileEmail, String message) {
        System.out.println("\nIterating over coworkers...\n");
        iterator = network.createCoworkersIterator(profileEmail);
        while (iterator.hasNext()) {
            Profile profile = iterator.getNext();
            sendMessage(profile.getEmail(), message);
        }
    }

    public void sendMessage(String email, String message) {
        System.out.println("Sent message to: '" + email + "'. Message body: '" + message + "'");
    }
}

实现方式:

public class Facebook implements SocialNetwork {

	 private List<Profile> profiles;

	    public Facebook(List<Profile> cache) {
	        if (cache != null) {
	            this.profiles = cache;
	        } else {
	            this.profiles = new ArrayList<>();
	        }
	    }

	    public Profile requestProfileFromFacebook(String profileEmail) {
	        // Here would be a POST request to one of the Facebook API endpoints.
	        // Instead, we emulates long network connection, which you would expect
	        // in the real life...
	        simulateNetworkLatency();
	        System.out.println("Facebook: Loading profile '" + profileEmail + "' over the network...");

	        // ...and return test data.
	        return findProfile(profileEmail);
	    }

	    public List<String> requestProfileFriendsFromFacebook(String profileEmail, String contactType) {
	        // Here would be a POST request to one of the Facebook API endpoints.
	        // Instead, we emulates long network connection, which you would expect
	        // in the real life...
	        simulateNetworkLatency();
	        System.out.println("Facebook: Loading '" + contactType + "' list of '" + profileEmail + "' over the network...");

	        // ...and return test data.
	        Profile profile = findProfile(profileEmail);
	        if (profile != null) {
	            return profile.getContacts(contactType);
	        }
	        return null;
	    }

	    private Profile findProfile(String profileEmail) {
	        for (Profile profile : profiles) {
	            if (profile.getEmail().equals(profileEmail)) {
	                return profile;
	            }
	        }
	        return null;
	    }

	    private void simulateNetworkLatency() {
	        try {
	            Thread.sleep(2500);
	        } catch (InterruptedException ex) {
	            ex.printStackTrace();
	        }
	    }

	    @Override
	    public ProfileIterator createFriendsIterator(String profileEmail) {
	        return new FacebookIterator(this, "friends", profileEmail);
	    }

	    @Override
	    public ProfileIterator createCoworkersIterator(String profileEmail) {
	        return new FacebookIterator(this, "coworkers", profileEmail);
	    }
}
public class FacebookIterator implements ProfileIterator {
    private Facebook facebook;
    private String type;
    private String email;
    private int currentPosition = 0;
    private List<String> emails = new ArrayList<>();
    private List<Profile> profiles = new ArrayList<>();

    public FacebookIterator(Facebook facebook, String type, String email) {
        this.facebook = facebook;
        this.type = type;
        this.email = email;
    }

    private void lazyLoad() {
        if (emails.size() == 0) {
            List<String> profiles = facebook.requestProfileFriendsFromFacebook(this.email, this.type);
            for (String profile : profiles) {
                this.emails.add(profile);
                this.profiles.add(null);
            }
        }
    }

    @Override
    public boolean hasNext() {
        lazyLoad();
        return currentPosition < emails.size();
    }

    @Override
    public Profile getNext() {
        if (!hasNext()) {
            return null;
        }

        String friendEmail = emails.get(currentPosition);
        Profile friendProfile = profiles.get(currentPosition);
        if (friendProfile == null) {
            friendProfile = facebook.requestProfileFromFacebook(friendEmail);
            profiles.set(currentPosition, friendProfile);
        }
        currentPosition++;
        return friendProfile;
    }

    @Override
    public void reset() {
        currentPosition = 0;
    }
}
public class LinkedIn implements SocialNetwork {

    private List<Profile> contacts;

    public LinkedIn(List<Profile> cache) {
        if (cache != null) {
            this.contacts = cache;
        } else {
            this.contacts = new ArrayList<>();
        }
    }

    public Profile requestContactInfoFromLinkedInAPI(String profileEmail) {
        // Here would be a POST request to one of the LinkedIn API endpoints.
        // Instead, we emulates long network connection, which you would expect
        // in the real life...
        simulateNetworkLatency();
        System.out.println("LinkedIn: Loading profile '" + profileEmail + "' over the network...");

        // ...and return test data.
        return findContact(profileEmail);
    }

    public List<String> requestRelatedContactsFromLinkedInAPI(String profileEmail, String contactType) {
        // Here would be a POST request to one of the LinkedIn API endpoints.
        // Instead, we emulates long network connection, which you would expect
        // in the real life.
        simulateNetworkLatency();
        System.out.println("LinkedIn: Loading '" + contactType + "' list of '" + profileEmail + "' over the network...");

        // ...and return test data.
        Profile profile = findContact(profileEmail);
        if (profile != null) {
            return profile.getContacts(contactType);
        }
        return null;
    }

    private Profile findContact(String profileEmail) {
        for (Profile profile : contacts) {
            if (profile.getEmail().equals(profileEmail)) {
                return profile;
            }
        }
        return null;
    }

    private void simulateNetworkLatency() {
        try {
            Thread.sleep(2500);
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }

    @Override
    public ProfileIterator createFriendsIterator(String profileEmail) {
        return new LinkedInIterator(this, "friends", profileEmail);
    }

    @Override
    public ProfileIterator createCoworkersIterator(String profileEmail) {
        return new LinkedInIterator(this, "coworkers", profileEmail);
    }

}
public class LinkedInIterator implements ProfileIterator {

	private LinkedIn linkedIn;
	private String type;
	private String email;
	private int currentPosition = 0;
	private List<String> emails = new ArrayList<>();
	private List<Profile> contacts = new ArrayList<>();

	public LinkedInIterator(LinkedIn linkedIn, String type, String email) {
		this.linkedIn = linkedIn;
		this.type = type;
		this.email = email;
	}

	private void lazyLoad() {
		if (emails.size() == 0) {
			List<String> profiles = linkedIn.requestRelatedContactsFromLinkedInAPI(this.email, this.type);
			for (String profile : profiles) {
				this.emails.add(profile);
				this.contacts.add(null);
			}
		}
	}

	@Override
	public boolean hasNext() {
		lazyLoad();
		return currentPosition < emails.size();
	}

	@Override
	public Profile getNext() {
		if (!hasNext()) {
			return null;
		}

		String friendEmail = emails.get(currentPosition);
		Profile friendContact = contacts.get(currentPosition);
		if (friendContact == null) {
			friendContact = linkedIn.requestContactInfoFromLinkedInAPI(friendEmail);
			contacts.set(currentPosition, friendContact);
		}
		currentPosition++;
		return friendContact;
	}

	@Override
	public void reset() {
		currentPosition = 0;
	}

}

测试:


	 public static Scanner scanner = new Scanner(System.in);

	    public static void main(String[] args) {
	        System.out.println("Please specify social network to target spam tool (default:Facebook):");
	        System.out.println("1. Facebook");
	        System.out.println("2. LinkedIn");
	        String choice = scanner.nextLine();

	        SocialNetwork network;
	        if (choice.equals("2")) {
	            network = new LinkedIn(createTestProfiles());
	        }
	        else {
	            network = new Facebook(createTestProfiles());
	        }

	        SocialSpammer spammer = new SocialSpammer(network);
	        spammer.sendSpamToFriends("anna.smith@bing.com",
	                "Hey! This is Anna's friend Josh. Can you do me a favor and like this post [link]?");
	        spammer.sendSpamToCoworkers("anna.smith@bing.com",
	                "Hey! This is Anna's boss Jason. Anna told me you would be interested in [link].");
	    }

	    public static List<Profile> createTestProfiles() {
	        List<Profile> data = new ArrayList<Profile>();
	        data.add(new Profile("anna.smith@bing.com", "Anna Smith", "friends:mad_max@ya.com", "friends:catwoman@yahoo.com", "coworkers:sam@amazon.com"));
	        data.add(new Profile("mad_max@ya.com", "Maximilian", "friends:anna.smith@bing.com", "coworkers:sam@amazon.com"));
	        data.add(new Profile("bill@microsoft.eu", "Billie", "coworkers:avanger@ukr.net"));
	        data.add(new Profile("avanger@ukr.net", "John Day", "coworkers:bill@microsoft.eu"));
	        data.add(new Profile("sam@amazon.com", "Sam Kitting", "coworkers:anna.smith@bing.com", "coworkers:mad_max@ya.com", "friends:catwoman@yahoo.com"));
	        data.add(new Profile("catwoman@yahoo.com", "Liza", "friends:anna.smith@bing.com", "friends:sam@amazon.com"));
	        return data;
	    }

测试结果:

Please specify social network to target spam tool (default:Facebook):
1. Facebook
2. LinkedIn
2

Iterating over friends...

LinkedIn: Loading 'friends' list of 'anna.smith@bing.com' over the network...
LinkedIn: Loading profile 'mad_max@ya.com' over the network...
Sent message to: 'mad_max@ya.com'. Message body: 'Hey! This is Anna's friend Josh. Can you do me a favor and like this post [link]?'
LinkedIn: Loading profile 'catwoman@yahoo.com' over the network...
Sent message to: 'catwoman@yahoo.com'. Message body: 'Hey! This is Anna's friend Josh. Can you do me a favor and like this post [link]?'

Iterating over coworkers...

LinkedIn: Loading 'coworkers' list of 'anna.smith@bing.com' over the network...
LinkedIn: Loading profile 'sam@amazon.com' over the network...
Sent message to: 'sam@amazon.com'. Message body: 'Hey! This is Anna's boss Jason. Anna told me you would be interested in [link].'

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

树懒_Zz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值