迭代器模式

迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示,类似于C++和Java的迭代器

迭代器模式结构

  • 迭代器接口:规定了遍历元素的方法
  • 具体迭代器:实现迭代器接口,包含遍历逻辑
  • 聚合类:定义一个接口用于返回一个迭代器对象

迭代器结构实现

// 迭代器接口
public interface Iterator {
public boolean hasNext();
public Object next();
}

// 聚合类
public interface Container {
public Iterator getIterator();
}

public class NameRepository implements Container {
public String[] names = {"Robert", "John", "Julie"};

@Override
public Iterator getIterator() {
return new Iterator();
}

private class NameIterator implements Iterator {
int index;

@Override
public boolean hasNext() {
if (index < name.length) {
return true;
}
return false;
}

@Override
public Object next() {
if (this.hasNext()) {
return names[index++];
}
return null;
}
}
}

public class Client {
public static void main(String[] args) {
NameRepository namesRepository = new NameRepository();

for(Iterator iter = namesRepository.getIterator(); iter.hasNext();){
String name = (String)iter.next();
System.out.println("Name : " + name);
}
}
}

优点

  • 支持多种遍历方式
  • 简化了聚合类
  • 多遍历支持
  • 拓展性更好

缺点

  • 系统复杂性增加

访问者模式

在访问者模式中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。

访问者模式结构

  • 访问者接口:包含访问不同元素的方法
  • 具体访问者:实现访问者接口,实现具体的访问不同元素的逻辑
  • 元素接口:包含一个接受访问者的方法
  • 具体元素:实现了元素接口,提供给访问者访问的入口

访问者模式实现

// 元素接口
public interface ComputerPart {
public void accept(ComputerPartVisitor computerPartVisitor);
}

// 具体元素
public class Keyboard implements ComputerPart {
@Override
public void accept(ComputerPartVisitor computerPartVisitor) {
computerPartVisitor.visit(this);
}
}

public class Monitor implements ComputerPart {
@Override
public void accept(ComputerPartVisitor computerPartVisitor) {
computerPartVisitor.visit(this);
}
}

public class Mouse implements ComputerPart {
@Override
public void accept(ComputerPartVisitor computerPartVisitor) {
computerPartVisitor.visit(this);
}
}

public class Computer implements ComputerPart {

ComputerPart[] parts;

public Computer(){
parts = new ComputerPart[] {new Mouse(), new Keyboard(), new Monitor()};
}


@Override
public void accept(ComputerPartVisitor computerPartVisitor) {
for (int i = 0; i < parts.length; i++) {
parts[i].accept(computerPartVisitor);
}
computerPartVisitor.visit(this);
}
}

// 访问者接口
public interface ComputerPartVisitor {
public void visit(Computer computer);
public void visit(Mouse mouse);
public void visit(Keyboard keyboard);
public void visit(Monitor monitor);
}

// 实体访问者
public class ComputerPartDisplayVisitor implements ComputerPartVisitor {

@Override
public void visit(Computer computer) {
System.out.println("Displaying Computer.");
}

@Override
public void visit(Mouse mouse) {
System.out.println("Displaying Mouse.");
}

@Override
public void visit(Keyboard keyboard) {
System.out.println("Displaying Keyboard.");
}

@Override
public void visit(Monitor monitor) {
System.out.println("Displaying Monitor.");
}
}

public class Client {
public static void main(String[] args) {
ComputerPart computer = new Computer();
computer.accept(new ComputerPartDisplayVisitor());
}
}

优点

  • 符合单一职责原则
  • 拓展性好
  • 灵活性好

缺点

  • 违反迪米特原则
  • 元素类难以变更
  • 依赖于具体类

备忘录模式

备忘录模式保存一个对象的某个状态,以便在适当的时候恢复对象,备忘录模式属于行为型模式。备忘录模式允许在不破坏封装性的前提下,捕获和恢复对象的内部状态。

备忘录模式结构

  • 备忘录:负责存储原发器对象的内部状态
  • 原发器:创建一个备忘录对象,并且可以使用备忘录对象恢复自身的内部状态
  • 负责人:负责保存备忘录对象,但是不对备忘录对象进行操作或检查

备忘录模式实现

public class Memento {
private String state;

public Memento(String state){
this.state = state;
}

public String getState(){
return state;
}
}

public class Originator {
private String state;

public void setState(String state){
this.state = state;
}

public String getState(){
return state;
}

public Memento saveStateToMemento(){
return new Memento(state);
}

public void getStateFromMemento(Memento Memento){
state = Memento.getState();
}
}

public class CareTaker {
private List<Memento> mementoList = new ArrayList<Memento>();

public void add(Memento state){
mementoList.add(state);
}

public Memento get(int index){
return mementoList.get(index);
}
}

public class MementoPatternDemo {
public static void main(String[] args) {
Originator originator = new Originator();
CareTaker careTaker = new CareTaker();
originator.setState("State #1");
originator.setState("State #2");
careTaker.add(originator.saveStateToMemento());
originator.setState("State #3");
careTaker.add(originator.saveStateToMemento());
originator.setState("State #4");

System.out.println("Current State: " + originator.getState());
originator.getStateFromMemento(careTaker.get(0));
System.out.println("First saved State: " + originator.getState());
originator.getStateFromMemento(careTaker.get(1));
System.out.println("Second saved State: " + originator.getState());
}
}

优点

  • 提供状态恢复机制
  • 封装了状态信息

缺点

  • 资源消耗大

解释器模式

解释器模式提供了评估语言的语法或表达式的方式,它属于行为型模式。

解释器模式给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

解释器模式结构

  • 抽象表达式:定义了解释器的抽象接口,声明了解释操作的方法,通常是一个抽象类或接口
  • 终结符表达式:实现了抽象表达式接口的终结符表达式类,用于表示语言中的终结符,并实现了对应的解释操作
  • 非终结符表达式:实现了抽象表达式接口的非终结符表达式类,用于表示语言中的非终结符,并实现了对应的解释操作
  • 上下文:包含解释器以外的一些全局信息

解释器模式实现

// 表达式接口
public interface Expression {
public boolean interpret(String context);
}

public class TerminalExpression implements Expression {

private String data;

public TerminalExpression(String data){
this.data = data;
}

@Override
public boolean interpret(String context) {
if(context.contains(data)){
return true;
}
return false;
}
}

public class OrExpression implements Expression {

private Expression expr1 = null;
private Expression expr2 = null;

public OrExpression(Expression expr1, Expression expr2) {
this.expr1 = expr1;
this.expr2 = expr2;
}

@Override
public boolean interpret(String context) {
return expr1.interpret(context) || expr2.interpret(context);
}
}

public class AndExpression implements Expression {

private Expression expr1 = null;
private Expression expr2 = null;

public AndExpression(Expression expr1, Expression expr2) {
this.expr1 = expr1;
this.expr2 = expr2;
}

@Override
public boolean interpret(String context) {
return expr1.interpret(context) && expr2.interpret(context);
}
}

public class Client {
//规则:Robert 和 John 是男性
public static Expression getMaleExpression(){
Expression robert = new TerminalExpression("Robert");
Expression john = new TerminalExpression("John");
return new OrExpression(robert, john);
}

//规则:Julie 是一个已婚的女性
public static Expression getMarriedWomanExpression(){
Expression julie = new TerminalExpression("Julie");
Expression married = new TerminalExpression("Married");
return new AndExpression(julie, married);
}

public static void main(String[] args) {
Expression isMale = getMaleExpression();
Expression isMarriedWoman = getMarriedWomanExpression();

System.out.println("John is male? " + isMale.interpret("John"));
System.out.println("Julie is a married women? "
+ isMarriedWoman.interpret("Married Julie"));
}
}

优点

  • 可拓展性好
  • 灵活性好
  • 易于实现简单的文法

缺点

  • 适用场景有限,只适合用于比较简单的文法
  • 维护困难,尤其是对于复杂的文法
  • 类膨胀,可能会出现很多的类
  • 递归调用