Iterator Pattern
Create your own custom Iterator so that it will iterate upons custom logic
Considering the following system
package designpatterns.iterator;
import java.util.HashMap;
import java.util.Map;
public class TemplateSystem {
private final Map<String, Template> templateIdToTemplate;
public TemplateSystem() {
templateIdToTemplate = new HashMap<>();
}
public void saveTemplate(Template userTemplate) {
Template template = new Template(userTemplate); // Use copy constructor here to avoid letting user modify the original object
Template previousTemplate = templateIdToTemplate.get(template.id);
if (previousTemplate != null) {
template.setVersion(previousTemplate.getVersion() + 1);
userTemplate.setVersion(template.getVersion()); // reflect the new change on user object
} else {
template.setVersion(0);
}
template.setPreviousTemplate(previousTemplate);
templateIdToTemplate.put(template.id, template);
}
public void searchAllVersion(Template template) {
VersionIterator templateIterator = new VersionIterator(templateIdToTemplate.get(template.id));
while (templateIterator.hasNext()) {
Template currentTemplate = templateIterator.next();
System.out.printf("%s: %s %s %n", currentTemplate.getVersion(), currentTemplate.templateName, currentTemplate.color);
}
}
}
With a custom VersionIterator
package designpatterns.iterator;
import java.util.Iterator;
public class VersionIterator implements Iterator<Template> {
private Template templateCursor;
public VersionIterator(Template template) {
templateCursor = template;
}
@Override
public boolean hasNext() {
return templateCursor != null;
}
@Override
public Template next() { // go back to previous version
Template currentTemplate = templateCursor;
templateCursor = templateCursor.getPreviousTemplate();
return currentTemplate;
}
}
package designpatterns.iterator;
import java.util.UUID;
public class Template {
public final String id;
public final String color;
public String templateName;
private Integer version;
private Template previousTemplate;
public Template(String color, String templateName) {
this.id = UUID.randomUUID().toString();
this.color = color;
this.templateName = templateName;
}
public Template(Template template) {
this.id = template.id;
this.color = template.color;
this.templateName = template.templateName;
this.version = template.version;
}
public Integer getVersion() {
return version;
}
public void setVersion(Integer version) {
this.version = version;
}
public Template getPreviousTemplate() {
return previousTemplate;
}
public void setPreviousTemplate(Template previousTemplate) {
this.previousTemplate = previousTemplate;
}
}
package designpatterns.iterator.test;
import designpatterns.iterator.Template;
import designpatterns.iterator.TemplateSystem;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class TemplateSystemTest {
@Test
void endToEnd_givenTemplateSystem_shouldIterateThroughPreviousTemplate() {
TemplateSystem templateSystem = new TemplateSystem();
Template firstTemplate = new Template("red", "my template name");
Template secondTemplate = new Template("blue", "my template name");
templateSystem.saveTemplate(firstTemplate);
templateSystem.saveTemplate(secondTemplate);
// Modification to the first template
firstTemplate.templateName = "another template name";
templateSystem.saveTemplate(firstTemplate);
firstTemplate.templateName = "yes template name";
templateSystem.saveTemplate(firstTemplate);
secondTemplate.templateName = "hi template name";
templateSystem.saveTemplate(secondTemplate);
assertEquals(2, firstTemplate.getVersion());
assertEquals(1, secondTemplate.getVersion());
templateSystem.searchAllVersion(firstTemplate);
templateSystem.searchAllVersion(secondTemplate);
}
}
2: yes template name red
1: another template name red
0: my template name red
1: hi template name blue
0: my template name blue
[!important]
Considering VersionControlSystem as alternative approaches