迭代器模式
简介
所谓迭代器模式,就是面向Iterator接口编程,无论底层的数据结构和迭代算法如何变化,调用者都不用修改代码;
高内聚,低耦合,才是程序设计之道。
一般很少需要自己写这个iterator模式,都是在集合编程中使用,尤其是如果要对集合元素遍历过程中做插入删除操作,那就用iterator,如果要对某个类中的集合进行遍历,由那个集合类返回一个iterator回来,统一面向iterator迭代器接口来编程遍历,提高系统整体的可维护性,可扩展性。
如果自己写iterator模式,一般是研发底层的框架,比如提供某个数据给外部遍历,那么可以使用iterator模式自己封装迭代器。
使用场景
集合迭代,遍历元素。
代码示例
package com.wc.designpattern.iterator;
import lombok.Data;
/**
* 迭代器模式
*/
public class IteratorPatternApplication {
@Data
static class Student {
private String name;
public Student(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
'}';
}
}
static class Classroom {
private Student[] students;
private int last = 0;
public Classroom(int size) {
this.students = new Student[size];
}
public Student getStudents(int index) {
return students[index];
}
public void addStudents(Student students) {
this.students[last] = students;
last ++;
}
public int getLength() {
return last;
}
public Iterator iterator() {
return new ClassroomIterator(this);
}
}
public interface Iterator {
boolean hasNext();
Object next();
}
static class ClassroomIterator implements Iterator {
private Classroom classroom;
private int index;
public ClassroomIterator(Classroom classroom) {
this.classroom = classroom;
this.index = 0;
}
@Override
public boolean hasNext() {
if (index < classroom.getLength()) {
return true;
} else {
return false;
}
}
@Override
public Object next() {
Student student = classroom.getStudents(index);
index ++;
return student;
}
}
public static void main(String[] args) {
Student s1 = new Student("lilei");
Student s2 = new Student("hanmeimei");
Classroom classroom = new Classroom(2);
classroom.addStudents(s1);
classroom.addStudents(s2);
Iterator iterator = classroom.iterator();
while (iterator.hasNext()) {
Student student = (Student) iterator.next();
System.out.println(student);
}
}
}
测试
执行Main函数,得到执行结果
Student{name='lilei'}
Student{name='hanmeimei'}
Process finished with exit code 0
适配器模式
简介
适配器模式,一般是在系统不断升级的过程中使用,对已经写好的老代码,写一套适配器来适配,但是提供新的接口。
还有一种情况,是对于已有的第三方类库,比如redis的客户端,或者是elasticsearch的客户端,他们提供了一套API,但是我们这里的要求是需要面向我们这里的DAO接口来进行编程,此时可以写一个适配器,将比如redis客户端的接口适配到我们的接口。
使用场景
(1)假设我们做了一个第一版的一个系统,这个系统里有一个接口和一个实现类
(2)接着我们开始做第二版的系统,这个系统我们定义了一个新的接口,和新的实现类
(3)但是我们同时在第二版的系统中,也要使用第一版系统中定义的那个老接口和老实现类
代码示例
没有使用设计模式
package com.wc.designpattern.adapter;
/**
* 不使用迭代器模式,就会出现新老两套接口,无法适配的问题
* 在使用的地方可能需要调用多套API,但是因为是新老两套接口,
* 会有很多重复的代码,就不是一个好的设计。
*/
public class NonPatternApplication {
public interface V1Interface {
void v1Execute();
}
static class V1InterfaceImpl implements V1Interface {
@Override
public void v1Execute() {
System.out.println("v1 operator...");
}
}
public interface V2Interface {
void v2Execute();
}
static class V2InterfaceImpl implements V2Interface {
@Override
public void v2Execute() {
System.out.println("v2 operator...");
}
}
public static void main(String[] args) {
V1Interface v1 = new V1InterfaceImpl();
V2Interface v2 = new V2InterfaceImpl();
v1.v1Execute();
v2.v2Execute();
}
}
使用适配器模式
package com.wc.designpattern.adapter;
/**
* 适配器模式
* 就是你手上有新老俩接口和一个老接口的实现类
* 但是现在系统中要面向新接口来开发,老接口的实现类就不能直接用了,不能直接面向老接口来开发
* 开发一个老接口到新接口的一个适配器
* 适配器是实现了新接口的,但是适配器中持有老接口实现类实例的引用
* 适配器的新接口方法的实现,全部基于老接口实现类的老方法来实现即可
* 对于调用方而言,只要使用适配器来开发即可,就可以通过面向新接口开发,底层使用老接口实现类
*
* @author WenChao
* @date 21/12/23
*/
public class AdapterPatternApplication {
public interface V1Interface {
void v1Execute();
}
static class V1InterfaceImpl implements V1Interface {
@Override
public void v1Execute() {
System.out.println("v1 operator...");
}
}
public interface V2Interface {
void v2Execute();
}
static class V2InterfaceImpl implements V2Interface {
@Override
public void v2Execute() {
System.out.println("v2 operator...");
}
}
/**
* 定义一个适配器类
*/
static class V2Adapter implements V2Interface {
private V1Interface v1Interface;
public V2Adapter(V1Interface v1Interface) {
this.v1Interface = v1Interface;
}
@Override
public void v2Execute() {
v1Interface.v1Execute();
}
}
public static void main(String[] args) {
V2Interface v1 = new V2Adapter(new V1InterfaceImpl());
V2Interface v2 = new V2InterfaceImpl();
v1.v2Execute();
v2.v2Execute();
}
}
测试
v1 operator...
v2 operator...
Process finished with exit code 0