Preface
In this article, Lizhi will introduce relevant knowledge about iterator pattern, visitor pattern and builder pattern. Among them, iterator and builder are relatively used more, and visitor pattern is relatively less used. . The key point is to understand the characteristics of different modes~ I hope it can help friends in need~~~
Article directory
1. Iterator pattern Iterator
The iterator pattern is generally used for containers and container traversal. The iterator pattern is generally adopted at the bottom of the basic data structure. The application of the iterator pattern is to provide us with a method to sequentially access each element in an aggregate object without explicit traversal logic inside the object.
In order to better understand this software design pattern, let’s take a look at this set of demos:
First create two interfaces, one is the iterator interface Iterator_, the other is the total interface Collection_ of the data structure
Define two more container classes ArrayList_ and LinkedList_. These two classes implement the Collection_ interface. This interface defines operations for adding data in the container, obtaining the size of the container, and providing traversal through the methods of the Iterator interface . interface methods . Two container classes are obtained by implementing the Collection_ interface and overriding the methods in this interface.
ArrayList_
package com.crj.Iterator;
class ArrayList_ implements Collection_ {
Object[] objects = new Object[10];
//objects中下一个空的位置在哪儿,或者说,目前容器中有多少个元素
private int index = 0;
public void add(Object o) {
if(index == objects.length) {
Object[] newObjects = new Object[objects.length*2];
System.arraycopy(objects, 0, newObjects, 0, objects.length);
objects = newObjects;
}
objects[index] = o;
index ++;
}
public int size() {
return index;
}
@Override
public Iterator_ iterator() {
return new ArrayListIterator();
}
private class ArrayListIterator implements Iterator_{
private int currentIndex = 0;
@Override
public boolean hasNext() {
if(currentIndex >= index) return false;
return true;
}
@Override
public Object next() {
Object o = objects[currentIndex];
currentIndex ++;
return o;
}
}
}
LinkedList_
package com.crj.Iterator;
/**
* 相比数组,这个容器不用考虑边界问题,可以动态扩展
*/
class LinkedList_ implements Collection_ {
Node head = null;
Node tail = null;
//目前容器中有多少个元素
private int size = 0;
public void add(Object o) {
Node n = new Node(o);
n.next = null;
if(head == null) {
head = n;
tail = n;
}
tail.next = n;
tail = n;
size++;
}
private class Node {
private Object o;
Node next;
public Node(Object o) {
this.o = o;
}
}
public int size() {
return size;
}
@Override
public Iterator_ iterator() {
return null;
}
}
main class
package com.crj.Iterator;
import java.util.Iterator;
public class Main {
public static void main(String[] args) {
Collection_ list = new ArrayList_();
for(int i=0; i<15; i++) {
list.add(new String("s" + i));
}
System.out.println(list.size());
//这个接口的调用方式:
Iterator_ it = list.iterator();
while(it.hasNext()) {
Object o = it.next();
System.out.println(o);
}
}
}
In main, we can see that we do not need to know the logic encapsulated in the two container classes and the corresponding logic implementation of traversing the internal elements of the container. We only need to use the pointer-like iterator method like .next(). You can get the elements in the container, which is the iterator pattern.
2. Visitor mode Visitor
To dynamically change the mode of internal element action while the structure remains unchanged, the Visitor mode is more suitable for the use of class objects with unchanged structure. The classes corresponding to the objects in the object structure rarely change, but it is often necessary to define new ones on this object structure. operation. The visitor mode is rarely used in daily use. One of its main application scenarios is to be a compiler. This mode is relatively simple to understand. Let's understand it through some code examples.
public class VisitorPatternDemo {
public static void main(String[] args) {
ComputerPart computer = new Computer();
computer.accept(new ComputerPartDisplayVisitor());
}
}
/*
* 接口
*/
interface ComputerPart {
public void accept(ComputerPartVisitor computerPartVisitor);
}
/*
* 接口实现类
*/
class Keyboard implements ComputerPart {
@Override
public void accept(ComputerPartVisitor computerPartVisitor) {
computerPartVisitor.visit(this);
}
}
class Mouse implements ComputerPart {
@Override
public void accept(ComputerPartVisitor computerPartVisitor) {
computerPartVisitor.visit(this);
}
}
/*
* 访问者接口
*/
interface ComputerPartVisitor {
public void visit(Mouse mouse);
public void visit(Keyboard keyboard);
}
//实现类
class ComputerPartDisplayVisitor implements ComputerPartVisitor {
@Override
public void visit(Mouse mouse) {
System.out.println("Displaying Mouse.");
}
@Override
public void visit(Keyboard keyboard) {
System.out.println("Displaying Keyboard.");
}
}
Different visitor interfaces provide corresponding implementation classes. By passing the visitor interface implementation class instantiation object into the instantiation method of ComputerPart, the corresponding method of the interface is called.
3. Builder mode Builder
The Builder Pattern uses multiple simple objects to build a complex object step by step. Targeted scenario: Many parameters need to be passed in the construction method of a class object. In order to abbreviate the demo, we can generate multiple objects through chain calls to obtain the final construction of complex class objects. We can understand through a demo example:
First define a TerrainBuilder interface, which defines four interface methods
package com.crj.builder;
public interface TerrainBuilder {
TerrainBuilder buildWall();
TerrainBuilder buildFort();
TerrainBuilder buildMine();
Terrain build();
}
Then define the implementation class of the interface. This interface implementation class implements the TerrainBuilder interface. In the demo, the four interface methods are rewritten. Finally, the terrain object is returned in the build() method.
package com.crj.builder;
public class ComplexTerrainBuilder implements TerrainBuilder {
Terrain terrain = new Terrain();
@Override
public TerrainBuilder buildWall() {
terrain.w = new Wall(10, 10, 50, 50);
return this;
}
@Override
public TerrainBuilder buildFort() {
terrain.f = new Fort(10, 10, 50, 50);
return this;
}
@Override
public TerrainBuilder buildMine() {
terrain.m = new Mine(10, 10, 50, 50);
return this;
}
@Override
public Terrain build() {
return terrain;
}
}
Object class
package com.crj.builder;
public class Terrain {
Wall w;
Fort f;
Mine m;
}
class Wall {
int x, y, w, h;
public Wall(int x, int y, int w, int h) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
}
}
class Fort {
int x, y, w, h;
public Fort(int x, int y, int w, int h) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
}
}
class Mine {
int x, y, w, h;
public Mine(int x, int y, int w, int h) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
}
}
Define main class
package com.crj.builder;
public class Main {
public static void main(String[] args) {
TerrainBuilder builder = new ComplexTerrainBuilder();
Terrain t = builder.buildFort().buildMine().buildWall().build();
}
}
In the main class, we can see that the instantiation of the Terrain class object is achieved by means of a series of chain calls instead of the traditional call to the parameterized constructor.
Summarize
For design patterns, we actually need to understand the theory, and there is no need to distinguish them in particular, because different software code patterns often contain multiple design patterns. Learning design patterns is still quite boring haha. After sorting out the output, I hope Lizhi will not forget it so quickly hahaha
Today has become the past, but we still look forward to the future tomorrow! I am Xiaolizhi, and I will accompany you on the road of technological growth. Coding is not easy, so please raise your little paw and give me a thumbs up, hahaha~~~ Bixinxin♥~~~