行为型模式的特点和分类

行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。

行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。

行为型模式是 GoF 设计模式中最为庞大的一类,它包含以下 11 种模式。

  1. 模板方法(Template Method)模式:定义一个操作中的算法骨架,将算法的一些步骤延迟到子类中,使得子类在可以不改变该算法结构的情况下重定义该算法的某些特定步骤。
  2. 策略(Strategy)模式:定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的改变不会影响使用算法的客户。
  3. 命令(Command)模式:将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。
  4. 职责链(Chain of Responsibility)模式:把请求从链中的一个对象传到下一个对象,直到请求被响应为止。通过这种方式去除对象之间的耦合。
  5. 状态(State)模式:允许一个对象在其内部状态发生改变时改变其行为能力。
  6. 观察者(Observer)模式:多个对象间存在一对多关系,当一个对象发生改变时,把这种改变通知给其他多个对象,从而影响其他对象的行为。
  7. 中介者(Mediator)模式:定义一个中介对象来简化原有对象之间的交互关系,降低系统中对象间的耦合度,使原有对象之间不必相互了解。
  8. 迭代器(Iterator)模式:提供一种方法来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。
  9. 访问者(Visitor)模式:在不改变集合元素的前提下,为一个集合中的每个元素提供多种访问方式,即每个元素有多个访问者对象访问。
  10. 备忘录(Memento)模式:在不破坏封装性的前提下,获取并保存一个对象的内部状态,以便以后恢复它。
  11. 解释器(Interpreter)模式:提供如何定义语言的文法,以及对语言句子的解释方法,即解释器。

模板方法模式

1. 模板方法模式的定义与特点

模式的定义与特点
模板方法(Template Method)模式的定义如下:定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。它是一种类行为型模式。

该模式的主要优点如下。

  1. 它封装了不变部分,扩展可变部分。它把认为是不变部分的算法封装到父类中实现,而把可变部分算法由子类继承实现,便于子类继续扩展。
  2. 它在父类中提取了公共的部分代码,便于代码复用。
  3. 部分方法是由子类实现的,因此子类可以通过扩展方式增加相应的功能,符合开闭原则。

2. 模板方法模式的结构与实现

模板方法模式的结构
模板方法模式包含以下主要角色。

(1) 抽象类(Abstract Class):负责给出一个算法的轮廓和骨架。它由一个模板方法和若干个基本方法构成。这些方法的定义如下。

① 模板方法:定义了算法的骨架,按某种顺序调用其包含的基本方法。

② 基本方法:是整个算法中的一个步骤,包含以下几种类型。
抽象方法:在抽象类中申明,由具体子类实现。
具体方法:在抽象类中已经实现,在具体子类中可以继承或重写它。
钩子方法:在抽象类中已经实现,包括用于判断的逻辑方法和需要子类重写的空方法两种。

(2) 具体子类(Concrete Class):实现抽象类中所定义的抽象方法和钩子方法,它们是一个顶级逻辑的一个组成步骤。

模板方法模式的实现

public abstract class AbstractClass {
    //基本方法
    protected abstract void doSomething();

    //基本方法
    protected abstract void doAnything();

    //模板方法
    public void templateMethod() {
        /*
        * 调用基本方法,完成相关的逻辑
        */
        this.doAnything();
        this.doSomething();
    }
}
blic class ConcreteClass1 extends AbstractClass {
    //实现基本方法
    protected void doAnything() {
//业务逻辑处理
    }

    protected void doSomething() {
//业务逻辑处理
    }
}
public class ConcreteClass2 extends AbstractClass {
    //实现基本方法
    protected void doAnything() {
//业务逻辑处理
    }

    protected void doSomething() {
//业务逻辑处理
    }
}

public class Client {
    public static void main(String[] args) {
        AbstractClass class1 = new ConcreteClass1();
        AbstractClass class2 = new ConcreteClass2();
        //调用模板方法
        class1.templateMethod();
        class2.templateMethod();
    }
}

3. 模板方法模式的应用场景

模板方法模式通常适用于以下场景。

  1. 算法的整体步骤很固定,但其中个别部分易变时,这时候可以使用模板方法模式,将容易变的部分抽象出来,供子类实现。
  2. 当多个子类存在公共的行为时,可以将其提取出来并集中到一个公共父类中以避免代码重复。首先,要识别现有代码中的不同之处,并且将不同之处分离为新的操作。最后,用一个调用这些新的操作的模板方法来替换这些不同的代码。
  3. 当需要控制子类的扩展时,模板方法只在特定点调用钩子操作,这样就只允许在这些点进行扩展。

4. 模板方法模式的扩展

钩子方法(Hook Method)来改变抽象父类中的运行结果。

策略模式

1. 策略模式的定义与特点

策略(Strategy)模式的定义:该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。
策略模式的主要优点如下。

  1. 多重条件语句不易维护,而使用策略模式可以避免使用多重条件语句。
  2. 策略模式提供了一系列的可供重用的算法族,恰当使用继承可以把算法族的公共代码转移到父类里面,从而避免重复的代码。
  3. 策略模式可以提供相同行为的不同实现,客户可以根据不同时间或空间要求选择不同的。
  4. 策略模式提供了对开闭原则的完美支持,可以在不修改原代码的情况下,灵活增加新算法。
  5. 策略模式把算法的使用放到环境类中,而算法的实现移到具体策略类中,实现了二者的分离。

2. 策略模式的结构与实现

模式的结构
策略模式的主要角色如下。

  1. 抽象策略(Strategy)类:定义了一个公共接口,各种不同的算法以不同的方式实现这个接口,环境角色使用这个接口调用不同的算法,一般使用接口或抽象类实现。
  2. 具体策略(Concrete Strategy)类:实现了抽象策略定义的接口,提供具体的算法实现。
  3. 环境(Context)类:持有一个策略类的引用,最终给客户端调用。

模式的实现

public interface Strategy {
//策略模式的运算法则
	public void doSomething();
}
public class ConcreteStrategy1 implements Strategy {
    public void doSomething() {
        System.out.println("具体策略1的运算法则");
    }
}

public class ConcreteStrategy2 implements Strategy {
    public void doSomething() {
        System.out.println("具体策略2的运算法则");
    }
}
public class Context {
    //抽象策略
    private Strategy strategy = null;

    //构造函数设置具体策略
    public Context(Strategy _strategy) {
        this.strategy = _strategy;
    }

    //封装后的策略方法
    public void doAnythinig() {
        this.strategy.doSomething();
    }
}
public class Client {
    public static void main(String[] args) {
//声明一个具体的策略
        Strategy strategy = new ConcreteStrategy1();
//声明上下文对象
        Context context = new Context(strategy);
//执行封装后的方法
        context.doAnythinig();
    }
}

3.策略模式的使用场景

  • 多个类只有在算法或行为上稍有不同的场景。
  • 算法需要自由切换的场景。
  • 需要屏蔽算法规则的场景。

命令模式

1. 命令模式的定义与特点

命令(Command)模式的定义如下:将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。这样两者之间通过命令对象进行沟通,这样方便将命令对象进行储存、传递、调用、增加与管理。

命令模式的主要优点如下。

  1. 降低系统的耦合度。命令模式能将调用操作的对象与实现该操作的对象解耦。
  2. 增加或删除命令非常方便。采用命令模式增加与删除命令不会影响其他类,它满足“开闭原则”,对扩展比较灵活。
  3. 可以实现宏命令。命令模式可以与组合模式结合,将多个命令装配成一个组合命令,即宏命令。
  4. 方便实现 Undo 和 Redo 操作。命令模式可以与后面介绍的备忘录模式结合,实现命令的撤销与恢复。

2.命令模式的结构与实现

模式的结构
命令模式包含以下主要角色。

  1. 抽象命令类(Command)角色:声明执行命令的接口,拥有执行命令的抽象方法 execute()。
  2. 具体命令角色(Concrete Command)角色:是抽象命令类的具体实现类,它拥有接收者对象,并通过调用接收者的功能来完成命令要执行的操作。
  3. 实现者/接收者(Receiver)角色:执行命令功能的相关操作,是具体命令对象业务的真正实现者。
  4. 调用者/请求者(Invoker)角色:是请求的发送者,它通常拥有很多的命令对象,并通过访问命令对象来执行相关请求,它不直接访问接收者。

模式的实现

public abstract class Receiver {
    //抽象接收者,定义每个接收者都必须完成的业务
    public abstract void doSomething();
}

public class ConcreteReciver1 extends Receiver {
    //每个接收者都必须处理一定的业务逻辑
    public void doSomething() {
    	System.out.println("ConcreteReciver1 开始处理");
    }
}

public class ConcreteReciver2 extends Receiver {
    //每个接收者都必须处理一定的业务逻辑
    public void doSomething() {
    	System.out.println("ConcreteReciver2 开始处理");
    }
}

public abstract class Command {
    //每个命令类都必须有一个执行命令的方法
    public abstract void execute();
}

public class ConcreteCommand1 extends Command {
    //对哪个Receiver类进行命令处理
    private Receiver receiver;

    //构造函数传递接收者
    public ConcreteCommand1(Receiver _receiver) {
        this.receiver = _receiver;
    }

    //必须实现一个命令
    public void execute() {
//业务处理
        this.receiver.doSomething();
    }
}

public class ConcreteCommand2 extends Command {
    //哪个Receiver类进行命令处理
    private Receiver receiver;

    //构造函数传递接收者
    public ConcreteCommand2(Receiver _receiver) {
        this.receiver = _receiver;
    }

    //必须实现一个命令
    public void execute() {
//业务处理
        this.receiver.doSomething();
    }
}

public class Invoker {
    private Command command;

    //受气包,接受命令
    public void setCommand(Command _command) {
        this.command = _command;
    }

    //执行命令
    public void action() {
        this.command.execute();
    }
}

public class Client {
    public static void main(String[] args) {
//首先声明调用者Invoker
        Invoker invoker = new Invoker();
//定义接收者
        Receiver receiver = new ConcreteReciver1();
//定义一个发送给接收者的命令
        Command command = new ConcreteCommand1(receiver);
//把命令交给调用者去执行
        invoker.setCommand(command);
        invoker.action();
    }
}

3.命令模式的应用

命令模式通常适用于以下场景。

  • 当系统需要将请求调用者与请求接收者解耦时,命令模式使得调用者和接收者不直接交互。
  • 当系统需要随机请求命令或经常增加或删除命令时,命令模式比较方便实现这些功能。
  • 当系统需要执行一组操作时,命令模式可以定义宏命令来实现该功能。
  • 当系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作时,可以将命令对象存储起来,采用备忘录模式来实现。

4.命令模式的扩展

责任链模式

1.模式的定义与特点

责任链(Chain of Responsibility)模式的定义:为了避免请求发送者与多个请求处理者耦合在一起,将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。
注意:责任链模式也叫职责链模式。

在责任链模式中,客户只需要将请求发送到责任链上即可,无须关心请求的处理细节和请求的传递过程,所以责任链将请求的发送者和请求的处理者解耦了

责任链模式是一种对象行为型模式,其主要优点如下。

  1. 降低了对象之间的耦合度。该模式使得一个对象无须知道到底是哪一个对象处理其请求以及链的结构,发送者和接收者也无须拥有对方的明确信息。
  2. 增强了系统的可扩展性。可以根据需要增加新的请求处理类,满足开闭原则。
  3. 增强了给对象指派职责的灵活性。当工作流程发生变化,可以动态地改变链内的成员或者调动它们的次序,也可动态地新增或者删除责任。
  4. 责任链简化了对象之间的连接。每个对象只需保持一个指向其后继者的引用,不需保持其他所有处理者的引用,这避免了使用众多的 if 或者 if···else 语句。
  5. 责任分担。每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。

2.模式的结构与实现

模式的结构
职责链模式主要包含以下角色。

  1. 抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。
  2. 具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。
  3. 客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。

模式的实现

package design.chain;
public abstract class Handler {
    private Handler nextHandler;

    //每个处理者都必须对请求做出处理
    public final Response handleMessage(Request request) {
        Response response = null;
//判断是否是自己的处理级别
        if (this.getHandlerLevel().equals(request.getRequestLevel())) {
            response = this.echo(request);
        } else { //不属于自己的处理级别
//判断是否有下一个处理者
            if (this.nextHandler != null) {
                response = this.nextHandler.handleMessage(request);
            } else {
//没有适当的处理者,业务自行处理
            }
        }
        return response;
    }

    //设置下一个处理者是谁
    public void setNext(Handler _handler) {
        this.nextHandler = _handler;
    }

    //每个处理者都有一个处理级别
    protected abstract Level getHandlerLevel();

    //每个处理者都必须实现处理任务
    protected abstract Response echo(Request request);
}

public class Level {
//定义一个请求和处理等级
}

public class Request {
    //请求的等级
    public Level getRequestLevel() {
        return null;
    }
}

public class Response {
//处理者返回的数据
}

public class ConcreteHandler1 extends Handler {
    //定义自己的处理逻辑
    protected Response echo(Request request) {
//完成处理逻辑
        return null;
    }

    //设置自己的处理级别
    protected Level getHandlerLevel() {
//设置自己的处理级别
        return null;
    }
}

public class ConcreteHandler2 extends Handler {
    //定义自己的处理逻辑
    protected Response echo(Request request) {
//完成处理逻辑
        return null;
    }

    //设置自己的处理级别
    protected Level getHandlerLevel() {
//设置自己的处理级别
        return null;
    }
}

public class ConcreteHandler3 extends Handler {
    //定义自己的处理逻辑
    protected Response echo(Request request) {
//完成处理逻辑
        return null;
    }

    //设置自己的处理级别
    protected Level getHandlerLevel() {
//设置自己的处理级别
        return null;
    }
}
public class Client {
    public static void main(String[] args) {
//声明所有的处理节点
        Handler handler1 = new ConcreteHandler1();
        Handler handler2 = new ConcreteHandler2();
        Handler handler3 = new ConcreteHandler3();
//设置链中的阶段顺序1-->2-->3
        handler1.setNext(handler2);
        handler2.setNext(handler3);
//提交请求,返回结果
        Response response = handler1.handlerMessage(new Request());
    }
}

状态模式

1.模式的定义与特点

状态模式的定义与特点
状态(State)模式的定义:对有状态的对象,把复杂的“判断逻辑”提取到不同的状态对象中,允许状态对象在其内部状态发生改变时改变其行为。
状态模式是一种对象行为型模式,其主要优点如下。

  1. 状态模式将与特定状态相关的行为局部化到一个状态中,并且将不同状态的行为分割开来,满足“单一职责原则”。
  2. 减少对象间的相互依赖。将不同的状态引入独立的对象中会使得状态转换变得更加明确,且减少对象间的相互依赖。
  3. 有利于程序的扩展。通过定义新的子类很容易地增加新的状态和转换。

2.状态模式的结构与实现

状态模式把受环境改变的对象行为包装在不同的状态对象里,其意图是让一个对象在其内部状态改变的时候,其行为也随之改变。现在我们来分析其基本结构和实现方法。
** 模式的结构**
状态模式包含以下主要角色。

  1. 环境(Context)角色:也称为上下文,它定义了客户感兴趣的接口,维护一个当前状态,并将与状态相关的操作委托给当前状态对象来处理。
  2. 抽象状态(State)角色:定义一个接口,用以封装环境对象中的特定状态所对应的行为。
  3. 具体状态(Concrete State)角色:实现抽象状态所对应的行为。
    模式的实现
public abstract class State {
    //定义一个环境角色,提供子类访问
    protected Context context;

    //设置环境角色
    public void setContext(Context _context) {
        this.context = _context;
    }

    //行为1
    public abstract void handle1();

    //行为2
    public abstract void handle2();
}
ublic

class ConcreteState1 extends State {
    @Override
    public void handle1() {
//本状态下必须处理的逻辑
    }

    @Override
    public void handle2() {
//设置当前状态为stat2
        super.context.setCurrentState(Context.STATE2);
//过渡到state2状态,由Context实现
        super.context.handle2();
    }
}

public class ConcreteState2 extends State {
    @Override
    public void handle1() {
//设置当前状态为state1
        super.context.setCurrentState(Context.STATE1);
//过渡到state1状态,由Context实现
        super.context.handle1();
    }

    @Override
    public void handle2() {
//本状态下必须处理的逻辑
    }
}

public class Context {
    //定义状态
    public final static State STATE1 = new ConcreteState1();
    public final static State STATE2 = new ConcreteState2();
    //当前状态
    private State CurrentState;

    //获得当前状态
    public State getCurrentState() {
        return CurrentState;
    }

    //设置当前状态
    public void setCurrentState(State currentState) {
        this.CurrentState = currentState;
//切换状态
        this.CurrentState.setContext(this);
    }

    //行为委托
    public void handle1() {
        this.CurrentState.handle1();
    }

    public void handle2() {
        this.CurrentState.handle2();
    }
}

public class Client {
    public static void main(String[] args) {
//定义环境角色
        Context context = new Context();
//初始化状态
        context.setCurrentState(new ConcreteState1());
//行为执行
        context.handle1();
        context.handle2();
    }
}

3.状态模式的应用

通常在以下情况下可以考虑使用状态模式。

  • 当一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为时,就可以考虑使用状态模式。
  • 一个操作中含有庞大的分支结构,并且这些分支决定于对象的状态时。

观察者模式

1.模式的定义与特点

模式的定义与特点
观察者(Observer)模式的定义:指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式,它是对象行为型模式。

观察者模式是一种对象行为型模式,其主要优点如下。

  1. 降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。
  2. 目标与观察者之间建立了一套触发机制。

2.模式的结构与实现

模式的结构
观察者模式的主要角色如下。

  1. 抽象主题(Subject)角色:也叫抽象目标类,它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。
  2. 具体主题(Concrete Subject)角色:也叫具体目标类,它实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。
  3. 抽象观察者(Observer)角色:它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。
  4. 具体观察者(Concrete Observer)角色:实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。

模式的实现

public interface Observable {
    //增加一个观察者
    public void addObserver(Observer observer);

    //删除一个观察者
    public void deleteObserver(Observer observer);

    //既然要观察,我发生改变了他也应该有所动作,通知观察者
    public void notifyObservers(String context);
}

public class HanFeiZi implements Observable, IHanFeiZi {
    //定义个变长数组,存放所有的观察者
    private ArrayList<Observer> observerList = new ArrayList<Observer>();

    //增加观察者
    public void addObserver(Observer observer) {
        this.observerList.add(observer);
    }

    //删除观察者
    public void deleteObserver(Observer observer) {
        this.observerList.remove(observer);
    }

    //通知所有的观察者
    public void notifyObservers(String context) {
        for (Observer observer : observerList) {
            observer.update(context);
        }
    }

    //韩非子要吃饭了
    public void haveBreakfast() {
        System.out.println("韩非子:开始吃饭了...");
        //通知所有的观察者
        this.notifyObservers("韩非子在吃饭");
    }

    //韩非子开始娱乐了
    public void haveFun() {
        System.out.println("韩非子:开始娱乐了...");
        this.notifyObservers("韩非子在娱乐");
    }
}

public interface Observer {
    //一发现别人有动静,自己也要行动起来
    public void update(String context);
}

public class LiSi implements Observer {
    //首先李斯是个观察者,一旦韩非子有活动,他就知道,他就要向老板汇报
    public void update(String str) {
        System.out.println("李斯:观察到韩非子活动,开始向老板汇报了...");
        this.reportToQinShiHuang(str);
        System.out.println("李斯:汇报完毕...\n");
    }

    //汇报给秦始皇
    private void reportToQinShiHuang(String reportContext) {
        System.out.println("李斯:报告,秦老板!韩非子有活动了-->" + reportContext);
    }
}

public class WangSi implements Observer {
    //王斯,看到韩非子有活动
    public void update(String str) {
        System.out.println("王斯:观察到韩非子活动,自己也开始活动了...");
        this.cry(str);
        System.out.println("王斯:哭死了...\n");
    }

    //一看韩非子有活动,他就痛哭
    private void cry(String context) {
        System.out.println("王斯:因为" + context + ",--所以我悲伤呀!");
    }
}

public class Client {
    public static void main(String[] args) {
//三个观察者产生出来
        Observer liSi = new LiSi();
        Observer wangSi = new WangSi();
        Observer liuSi = new LiuSi();
//定义出韩非子
        HanFeiZi hanFeiZi = new HanFeiZi();
//我们后人根据历史,描述这个场景,有三个人在观察韩非子
        hanFeiZi.addObserver(liSi);
        hanFeiZi.addObserver(wangSi);
        hanFeiZi.addObserver(liuSi);
//然后这里我们看看韩非子在干什么
        hanFeiZi.haveBreakfast();
    }
}

public interface IHanFeiZi {
    //韩非子也是人,也要吃早饭的
    public void haveBreakfast();

    //韩非之也是人,是人就要娱乐活动
    public void haveFun();
}

3.观察者模式的应用

  • 关联行为场景。需要注意的是,关联行为是可拆分的,而不是“组合”关系。
  • 事件多级触发场景。
  • 跨系统的消息交换场景,如消息队列的处理机制。

中介者模式

1.模式的定义与特点

中介者(Mediator)模式的定义:定义一个中介对象来封装一系列对象之间的交互,使原有对象之间的耦合松散,且可以独立地改变它们之间的交互。中介者模式又叫调停模式,它是迪米特法则的典型应用。

中介者模式是一种对象行为型模式,其主要优点如下。

  1. 降低了对象之间的耦合性,使得对象易于独立地被复用。
  2. 将对象间的一对多关联转变为一对一的关联,提高系统的灵活性,使得系统易于维护和扩展。

2.模式的结构与实现

中介者模式实现的关键是找出“中介者”,下面对它的结构和实现进行分析。
模式的结构
中介者模式包含以下主要角色。

  1. 抽象中介者(Mediator)角色:它是中介者的接口,提供了同事对象注册与转发同事对象信息的抽象方法。
  2. 具体中介者(ConcreteMediator)角色:实现中介者接口,定义一个 List来管理同事对象,协调各个同事角色之间的交互关系,因此它依赖于同事角色。
  3. 抽象同事类(Colleague)角色:定义同事类的接口,保存中介者对象,提供同事对象交互的抽象方法,实现所有相互影响的同事类的公共功能。
  4. 具体同事类(Concrete Colleague)角色:是抽象同事类的实现者,当需要与其他同事对象交互时,由中介者对象负责后续的交互。

模式的实现

/**
 * @author wx
 * @create 2019/11/11
 * @version 1.0.0
 * @description
 * @since 1.0.0
 */
package design.mediator;

/**
 * @author wx
 * @version 1.0.0
 * @create 2019/11/11
 * @since 1.0.0
 */
public abstract class Mediator {
    //定义同事类
    protected ConcreteColleague1 c1;
    protected ConcreteColleague2 c2;

    //通过getter/setter方法把同事类注入进来
    public ConcreteColleague1 getC1() {
        return c1;
    }

    public void setC1(ConcreteColleague1 c1) {
        this.c1 = c1;
    }

    public ConcreteColleague2 getC2() {
        return c2;
    }

    public void setC2(ConcreteColleague2 c2) {
        this.c2 = c2;
    }

    //中介者模式的业务逻辑
    public abstract void doSomething1();

    public abstract void doSomething2();
}

public class ConcreteMediator extends Mediator {
    @Override
    public void doSomething1() {
//调用同事类的方法,只要是public方法都可以调用
        super.c1.selfMethod1();
        super.c2.selfMethod2();
    }

    public void doSomething2() {
        super.c1.selfMethod1();
        super.c2.selfMethod2();
    }
}

public abstract class Colleague {
    protected Mediator mediator;

    public Colleague(Mediator _mediator) {
        this.mediator = _mediator;
    }
}

public class ConcreteColleague1 extends Colleague {
    //通过构造函数传递中介者
    public ConcreteColleague1(Mediator _mediator) {
        super(_mediator);
    }

    //自有方法 self-method
    public void selfMethod1() {
//处理自己的业务逻辑
    }

    //依赖方法 dep-method
    public void depMethod1() {
//处理自己的业务逻辑
//自己不能处理的业务逻辑,委托给中介者处理
        super.mediator.doSomething1();
    }
}

public class ConcreteColleague2 extends Colleague {
    //通过构造函数传递中介者
    public ConcreteColleague2(Mediator _mediator) {
        super(_mediator);
    }

    //自有方法 self-method
    public void selfMethod2() {
//处理自己的业务逻辑
    }

    //依赖方法 dep-method
    public void depMethod2() {
//处理自己的业务逻辑
//自己不能处理的业务逻辑,委托给中介者处理
        super.mediator.doSomething2();
    }
}

3.中介模式的应用

  • N个对象之间产生了相互的依赖关系(N>2)。
  • 多个对象有依赖关系,但是依赖的行为尚不确定或者有发生改变的可能,在这种情况下一般建议采用中介者模式,降低变更引起的风险扩散。
  • 产品开发。

迭代器模式

1.模式的定义与特点

迭代器(Iterator)模式的定义:提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。

迭代器模式是一种对象行为型模式,其主要优点如下。

  1. 访问一个聚合对象的内容而无须暴露它的内部表示。
  2. 遍历任务交由迭代器完成,这简化了聚合类。
  3. 它支持以不同方式遍历一个聚合,甚至可以自定义迭代器的子类以支持新的遍历。
  4. 增加新的聚合类和迭代器类都很方便,无须修改原有代码。
  5. 封装性良好,为遍历不同的聚合结构提供一个统一的接口。

2.模式的结构与实现

迭代器模式是通过将聚合对象的遍历行为分离出来,抽象成迭代器类来实现的,其目的是在不暴露聚合对象的内部结构的情况下,让外部代码透明地访问聚合的内部数据。现在我们来分析其基本结构与实现方法。
模式的结构
迭代器模式主要包含以下角色。
抽象聚合(Aggregate)角色:定义存储、添加、删除聚合对象以及创建迭代器对象的接口。
具体聚合(ConcreteAggregate)角色:实现抽象聚合类,返回一个具体迭代器的实例。
抽象迭代器(Iterator)角色:定义访问和遍历聚合元素的接口,通常包含 hasNext()、first()、next() 等方法。
具体迭代器(Concretelterator)角色:实现抽象迭代器接口中所定义的方法,完成对聚合对象的遍历,记录遍历的当前位置。

模式的实现

public interface Iterator {
    //遍历到下一个元素
    public Object next();

    //是否已经遍历到尾部
    public boolean hasNext();

    //删除当前指向的元素
    public boolean remove();
}

public class ConcreteIterator implements Iterator {
    private Vector vector = new Vector();
    //定义当前游标
    public int cursor = 0;

    @SuppressWarnings("unchecked")
    public ConcreteIterator(Vector _vector) {
        this.vector = _vector;
    }

    //判断是否到达尾部
    public boolean hasNext() {
        if (this.cursor == this.vector.size()) {
            return false;
        } else {
            return true;
        }
    }

    //返回下一个元素
    public Object next() {
        Object result = null;
        if (this.hasNext()) {
            result = this.vector.get(this.cursor++);
        } else {
            result = null;
        }
        return result;
    }

    //删除当前元素
    public boolean remove() {
        this.vector.remove(this.cursor);
        return true;
    }
}

public interface Aggregate {
    //是容器必然有元素的增加
    public void add(Object object);

    //减少元素
    public void remove(Object object);

    //由迭代器来遍历所有的元素
    public Iterator iterator();
}

public class ConcreteAggregate implements Aggregate {
    //容纳对象的容器
    private Vector vector = new Vector();

    //增加一个元素
    public void add(Object object) {
        this.vector.add(object);
    }

    //返回迭代器对象
    public Iterator iterator() {
        return new ConcreteIterator(this.vector);
    }

    //删除一个元素
    public void remove(Object object) {
        this.remove(object);
    }
}

public class Client {
    public static void main(String[] args) {
//声明出容器
        Aggregate agg = new ConcreteAggregate();
//产生对象数据放进去
        agg.add("abc");
        agg.add("aaa");
        agg.add("1234");
//遍历一下
        Iterator iterator = agg.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}

访问者模式

1.模式的定义与特点

访问者(Visitor)模式的定义:将作用于某种数据结构中的各元素的操作分离出来封装成独立的类,使其在不改变数据结构的前提下可以添加作用于这些元素的新的操作,为数据结构中的每个元素提供多种访问方式。它将对数据的操作与数据结构进行分离,是行为类模式中最复杂的一种模式

访问者(Visitor)模式是一种对象行为型模式,其主要优点如下。

  1. 扩展性好。能够在不修改对象结构中的元素的情况下,为对象结构中的元素添加新的功能。
  2. 复用性好。可以通过访问者来定义整个对象结构通用的功能,从而提高系统的复用程度。
  3. 灵活性好。访问者模式将数据结构与作用于结构上的操作解耦,使得操作集合可相对自由地演化而不影响系统的数据结构。
  4. 符合单一职责原则。访问者模式把相关的行为封装在一起,构成一个访问者,使每一个访问者的功能都比较单一。

2.模式的结构与实现

模式的结构
访问者模式包含以下主要角色。

  1. 抽象访问者(Visitor)角色:定义一个访问具体元素的接口,为每个具体元素类对应一个访问操作 visit(),该操作中的参数类型标识了被访问的具体元素。
  2. 具体访问者(ConcreteVisitor)角色:实现抽象访问者角色中声明的各个访问操作,确定访问者访问一个元素时该做什么。
  3. 抽象元素(Element)角色:声明一个包含接受操作 accept() 的接口,被接受的访问者对象作为 accept() 方法的参数。
  4. 具体元素(ConcreteElement)角色:实现抽象元素角色提供的 accept() 操作,其方法体通常都是visitor.visit(this) ,另外具体元素中可能还包含本身业务逻辑的相关操作。
  5. 对象结构(Object Structure)角色:是一个包含元素角色的容器,提供让访问者对象遍历容器中的所有元素的方法,通常由
    List、Set、Map 等聚合类实现。
Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐