深入浅出Java23种设计模式(三)

行为模式

责任链模式

一、概述

使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链, 并沿着这条链传递该请求,直到有一个对象处理它为止。 这一模式的想法是,给多个对象处理一个请求的机会,从而解耦发送者和接受者。

二、适用性

  • 有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定。
  • 在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
  • 可处理一个请求的对象集合应被动态指定。

三、参与者

  • Handler定义一个处理请求的接口。 (可选)实现后继链。
  • ConcreteHandler 处理它所负责的请求。 可访问它的后继者。 如果可处理该请求,就处理之;否则将该请求转发给它的后继者。
  • Client 向链上的具体处理者(ConcreteHandler)对象提交请求。

四、类图

在这里插入图片描述

五、示例

  • Handler
package com.cz.Adaptermode.cor;

import org.omg.CORBA.Request;

/**
 * @Author: zhang
 * @Date: 2021/3/31 - 19:32
 * @Descripetion: Handler
 **/
public interface RequestHandle {
    void handleRequest(Request request);
}

ConcreteHandler

package com.cz.Adaptermode.cor;

import org.omg.CORBA.Request;

/**
 * @Author: zhang
 * @Date: 2021/3/31 - 19:34
 * @Descripetion: ConcreteHandler
 **/
public class HRRequestHandle implements RequestHandle {

    @Override
    public void handleRequest(Request request) {
        if (request instanceof DimissionRequest){
            System.out.println("想辞职,不可能的!");
        }
        System.out.println("请求完毕");
    }
}
package com.cz.Adaptermode.cor;

import org.omg.CORBA.Request;

/**
 * @Author: zhang
 * @Date: 2021/3/31 - 19:36
 * @Descripetion: ConcreteHandler
 **/
public class PMRequestHandle implements RequestHandle {

    RequestHandle requestHandle;

    public PMRequestHandle(RequestHandle requestHandle){
        this.requestHandle = requestHandle;
    }

    @Override
    public void handleRequest(Request request) {
        if (request instanceof AddMoneyRequest){
            System.out.println("想加薪?不可能的!");
        }else {
            request.handleRequest(request);
        }
    }
}
package com.cz.Adaptermode.cor;

import org.omg.CORBA.Request;

/**
 * @Author: zhang
 * @Date: 2021/3/31 - 19:39
 * @Descripetion: ConcreteHandler
 **/
public class TLRequestHandle implements RequestHandle{

    RequestHandle requestHandle;

    public TLRequestHandle(RequestHandle requestHandle){
        this.requestHandle = requestHandle;
    }

    @Override
    public void handleRequest(Request request) {
        if (request instanceof LeaveRequest){
            System.out.println("要请假?不可能的!");
        }else {
            request.handleRequest(request);
        }
    }
}
  • Test
import org.omg.CORBA.Request;
/**
 * @Author: zhang
 * @Date: 2021/3/31 - 19:39
 * @Descripetion: ConcreteHandler
 **/
public class Test { 
	public static void main(String[] args) {
		RequestHandle hr = new HRRequestHandle(); 
		RequestHandle pm = new PMRequestHandle(hr); 
		RequestHandle tl = new TLRequestHandle(pm);
		
		//team leader处理离职请求 
		Request request = new Request(); 
		tl.handleRequest(request);

		System.out.println("==========="); 
		//team leader处理加薪请求 
		request = new AddMoneyRequest(); 
		tl.handleRequest(request); 
		System.out.println("========"); 
		//项目经理上理辞职请求 
		request = new DimissionRequest(); 
		pm.handleRequest(request);
	}
}

命令模式

一、概述

将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作。

二、适用性

  • 抽象出待执行的动作以参数化某对象。
  • 在不同的时刻指定、排列和执行请求。
  • 支持取消操作。
  • 支持修改日志,这样当系统崩溃时,这些修改可以被重做一遍。
  • 用构建在原语操作上的高层操作构造一个系统。

三、参与者

  • Command声明执行操作的接口。
  • ConcreteCommand 将一个接收者对象绑定于一个动作。 调用接收者相应的操作,以实现Execute
  • Client 创建一个具体命令对象并设定它的接收者。
  • Invoker 要求该命令执行这个请求。
  • Receiver 知道如何实施与执行一个请求相关的操作。任何类都可能作为一个接收者

四、类图

在这里插入图片描述

五、示例

  • Command
package com.cz.Adaptermode.command;



/**
 * @Author: zhang
 * @Date: 2021/4/1 - 19:04
 * @Descripetion: Command
 **/
public abstract class Command {

    protected Receiver receiver;

    public Command(Receiver receiver){
        this.receiver = receiver;
    }

    public abstract void execute();
}
  • ConcreteCommand
package com.cz.Adaptermode.command;

/**
 * @Author: zhang
 * @Date: 2021/4/1 - 19:06
 * @Descripetion: ConcreteCommand
 **/
public class CommandImpl extends Command {

    public CommandImpl(Receiver receiver){
        super(receiver);
    }

    @Override
    public void execute() {
        receiver.request();
    }
}
  • Invoker
package com.cz.Adaptermode.command;

/**
 * @Author: zhang
 * @Date: 2021/4/1 - 19:07
 * @Descripetion: Invoker
 **/
public class Invoker {

    private Command command;

    public void setCommand(Command command) {
        this.command = command;
    }

    public void execute(){
        command.execute();
    }
}
  • Receiver
package com.cz.Adaptermode.command;

/**
 * @Author: zhang
 * @Date: 2021/4/1 - 19:09
 * @Descripetion: Receiver
 **/
public class Receiver {

    public void request() {
        System.out.println("This is Receive class!");
    }
}
  • Test
package com.cz.Adaptermode.command;

/**
 * @Author: zhang
 * @Date: 2021/4/1 - 19:13
 * @Descripetion: 测试类
 **/
public class Test {
    public static void main(String[] args) {
        Receiver receiver = new Receiver();
        Command command = new CommandImpl(receiver);
        Invoker invoker = new Invoker();

        invoker.setCommand(command);
        invoker.execute();
    }
}
  • 运行结果:
    在这里插入图片描述

解析器模式

一、概述

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

二、适用性

当有一个语言需要解释执行,并且你可将该语言中的句子表示为一个抽象语法树时,可使 用解释器模式。而当存在以下情况时该模式效果最好:

  • 该文法简单对于复杂的文法,文法的类层次变得庞大而无法管理。
  • 效率不是一个关键问题最高效的解释器通常不是通过直接解释语法分析树实现的,而是首先将它们转换成另一种形式。

三、参与者

  • AbstractExpression(抽象表达式) 声明一个抽象的解释操作,这个接口为抽象语法树中所有的节点所共享。
  • TerminalExpression(终结符表达式) 实现与文法中的终结符相关联的解释操作。 一个句子中的每个终结符需要该类的一个实例。
  • NonterminalExpression(非终结符表达式) 为文法中的非终结符实现解释(Interpret)操作。
  • Context上下文) 包含解释器之外的一些全局信息。
  • Client客户) 构建(或被给定)表示该文法定义的语言中一个特定的句子的抽象语法树。 该抽象语法树由NonterminalExpressionTerminalExpression的实例装配而成。 调用解释操作。

四、类图

在这里插入图片描述

五、示例

  • AbstractExpression
package com.cz.Adaptermode.interpreter;

/**
 * @Author: zhang
 * @Date: 2021/4/1 - 19:18
 * @Descripetion: AbstractExpression
 **/
public abstract class Expression {

    abstract void interpret(Context context);
}
  • Expression
package com.cz.Adaptermode.interpreter;

/**
 * @Author: zhang
 * @Date: 2021/4/1 - 19:19
 * @Descripetion: Expression
 **/
public class AdvanceExpression extends Expression {
    
    @Override
    void interpret(Context context) {
        System.out.println("这是高级解析器!");
    }
}
package com.cz.Adaptermode.interpreter;

/**
 * @Author: zhang
 * @Date: 2021/4/1 - 19:20
 * @Descripetion: Expression
 **/
public class SimpleExpression extends Expression {
    
    @Override
    void interpret(Context context) {
        System.out.println("这是普通解析器!");
    }
}
  • Context
package com.cz.Adaptermode.interpreter;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author: zhang
 * @Date: 2021/4/1 - 19:21
 * @Descripetion: Context
 **/
public class Context {

    private String contnent;
    private List<Expression> list = new ArrayList<Expression>();

    public String getContnent() {
        return this.contnent;
    }

    public void setContnent(String contnent) {
        this.contnent = contnent;
    }

    public void add(Expression expression){
        list.add(expression);
    }

    public List<Expression> getList(){
        return list;
    }
}
  • Test
package com.cz.Adaptermode.interpreter;

/**
 * @Author: zhang
 * @Date: 2021/4/1 - 19:25
 * @Descripetion: Test
 **/
public class Test {
    public static void main(String[] args) {
        Context context = new Context();
        context.add(new SimpleExpression());
        context.add(new AdvanceExpression());
        context.add(new SimpleExpression());

        for (Expression expression : context.getList()){
            expression.interpret(context);
        }
    }
}
  • 运行结果:
    在这里插入图片描述

迭代器模式

一、概述

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

二、适用性

  • 访问一个聚合对象的内容而无需暴露它的内部表示。
  • 支持对聚合对象的多种遍历。
  • 为遍历不同的聚合结构提供一个统一的接口(即,支持多态迭代)。

参与者

  • Iterator迭代器定义访问和遍历元素的接口。
  • ConcreteIterator具体迭代器实现迭代器接口。 对该聚合遍历时跟踪当前位置。
  • Aggregate聚合定义创建相应迭代器对象的接口。
  • ConcreteAggregate具体聚合实现创建相应迭代器的接口,该操作返回ConcreteIterator的一个适当的实例.

四、类图

在这里插入图片描述

五、示例

  • Iterator
package com.cz.Adaptermode.iterator;

/**
 * @Author: zhang
 * @Date: 2021/4/1 - 19:29
 * @Descripetion: Iterator
 **/
public interface Iterator {

    Object next();
    void first();
    void last();
    boolean hasNext();
}
  • ConcreteIterator
package com.cz.Adaptermode.iterator;

/**
 * @Author: zhang
 * @Date: 2021/4/1 - 19:31
 * @Descripetion: ConcreteIterator
 **/
public class IteratorImpl implements Iterator {

    private List list;
    private int index;

    public IteratorImpl(List list){
        index = 0;
        this.list = list;
    }

    @Override
    public Object next() {
        Object obj = list.get(index);
        index ++;
        return obj;
    }

    @Override
    public void first() {
        index = 0;
    }

    @Override
    public void last() {
        index = list.getSize();
    }

    @Override
    public boolean hasNext() {
        return index < list.getSize();
    }
}
  • Aggregate
package com.cz.Adaptermode.iterator;

/**
 * @Author: zhang
 * @Date: 2021/4/1 - 19:35
 * @Descripetion: Aggregate
 **/
public interface List {

    Iterator iterator();
    Object get(int index);
    int getSize();
    void add(Object obj);
}
  • ConcreteAggregate
package com.cz.Adaptermode.iterator;

/**
 * @Author: zhang
 * @Date: 2021/4/1 - 19:37
 * @Descripetion: ConcreteAggregate
 **/
public class ListImpl implements List {

    private Object[] list;
    private int index;
    private int size;

    public ListImpl(){
        index = 0;
        size = 0;
        list = new Object[100];
    }

    @Override
    public Iterator iterator() {
        return new IteratorImpl(this);
    }

    @Override
    public Object get(int index) {
        return list[index];
    }

    @Override
    public int getSize() {
        return this.size;
    }

    @Override
    public void add(Object obj) {
        list[index ++] = obj;
        size ++;
    }
}
  • Test
package com.cz.Adaptermode.iterator;

/**
 * @Author: zhang
 * @Date: 2021/4/1 - 19:40
 * @Descripetion: Test
 **/
public class Test {
    public static void main(String[] args) {
        List list = new ListImpl();
        list.add("a");
        list.add("b");
        list.add("c");

        //第一种迭代方式
        System.out.println("第一种迭代方式");
        Iterator iterator = list.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }

        System.out.println("================");
        //第二种迭代方式
        System.out.println("第二种迭代方式");
        for (int i = 0; i < list.getSize(); i++){
            System.out.println(list.get(i));
        }
    }
}
  • 运行结果:
    在这里插入图片描述

中介者模式

一、概述

用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

二、适用性

  • 一组对象以定义良好但是复杂的方式进行通信。产生的相互依赖关系结构混乱且难以理解。
  • 一个对象引用其他很多对象并且直接与这些对象通信,导致难以复用该对象。
  • 定制一个分布在多个类中的行为,而又不想生成太多的子类。

三、参与者

  • Mediator 中介者定义一个接口用于与各同事(Colleague)对象通信。
  • ConcreteMediator具体中介者通过协调各同事对象实现协作行为。 了解并维护它的各个同事。
  • Colleagueclass每一个同事类都知道它的中介者对象。 每一个同事对象在需与其他的同事通信的时候,与它的中介者通信

四、类图

在这里插入图片描述

五、示例

  • Mediator
package com.cz.Adaptermode.mediator;

/**
 * @Author: zhang
 * @Date: 2021/4/1 - 19:46
 * @Descripetion: Mediator
 **/
public abstract class Mediator {

    //申明一个联络方法
    public abstract void constact(String message,Colleague colleague);
}

  • ConcreteMediator
package com.cz.Adaptermode.mediator;

/**
 * @Author: zhang
 * @Date: 2021/4/1 - 19:47
 * @Descripetion: ConcreteMediator
 **/
public class ConcreteMediator extends Mediator {

    // 首先中介结构必须知道所有房主和租房者的信息
    private ColleagueA colleagueA;
    private ColleagueB colleagueB;

    public void setColleague(ColleagueA colleagueA, ColleagueB colleagueB) {
        this.colleagueA = colleagueA;
        this.colleagueB = colleagueB;
    }

    public void constact(String message, Colleague colleague) {
        if(colleague == colleagueA){
            //如果是房主,则租房者获得信息
            colleagueB.getMessage(message);
        } else {
            // 否者则是房主获得信息
            colleagueA.getMessage(message);
        }
    }
}

  • Colleague
package com.cz.Adaptermode.mediator;

/**
 * @Author: zhang
 * @Date: 2021/4/2 - 12:19
 * @Descripetion: Colleague
 **/
public class Colleague {

    protected String name;
    protected Mediator mediator;

    Colleague(String name,Mediator mediator){
        this.name = name;
        this.mediator = mediator;
    }
}

  • Colleagueclass
package com.cz.Adaptermode.mediator;

/**
 * @Author: zhang
 * @Date: 2021/4/1 - 19:52
 * @Descripetion: Colleagueclass
 **/
public class ColleagueA extends Colleague {


    ColleagueA(String name, Mediator mediator) {
        super(name, mediator);
    }

    public void constact(String message){
        mediator.constact(message, this);
    }

    public void getMessage(String message){
        System.out.println("房主:" + name +",获得信息:" + message);
    }
}
package com.cz.Adaptermode.mediator;

/**
 * @Author: zhang
 * @Date: 2021/4/1 - 19:54
 * @Descripetion: Colleagueclass
 **/
public class ColleagueB extends Colleague {


    ColleagueB(String name, Mediator mediator) {
        super(name, mediator);
    }

    public void constact(String message){
        mediator.constact(message, this);
    }

    public void getMessage(String message){
        System.out.println("租房者:" + name +",获得信息:" + message);
    }
}
  • Test
package com.cz.Adaptermode.mediator;

/**
 * @Author: zhang
 * @Date: 2021/4/2 - 12:23
 * @Descripetion: 测试类
 **/
public class Tset {
    public static void main(String[] args) {
        ConcreteMediator mediator = new ConcreteMediator();

        // 房主和租房者只需要知道中介机构即可
        ColleagueA colleagueA = new ColleagueA("张三", mediator);
        ColleagueB colleagueB = new ColleagueB("李四", mediator);

        //中介结构要知道房主和租房者
        mediator.setColleague(colleagueA, colleagueB);

        colleagueB.constact("听说你那有房出租");
        colleagueA.constact("是的");
    }
}
  • 运行结果:
    在这里插入图片描述

备忘录模式

一、概述

在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。

二、适用性

  • 必须保存一个对象在某一个时刻的(部分)状态,这样以后需要时它才能恢复到先前的状态。
  • 如果一个用接口来让其它对象直接得到这些状态,将会暴露对象的实现细节并破坏对象的封装性。

三、参与者

  • Memento备忘录存储原发器对象的内部状态。
  • Originator原发器创建一个备忘录,用以记录当前时刻它的内部状态。 使用备忘录恢复内部状态.
  • Caretaker负责保存好备忘录。 不能对备忘录的内容进行操作或检查。

四、类图

在这里插入图片描述

五、示例

  • Memento
package com.cz.Adaptermode.memento;

/**
 * @Author: zhang
 * @Date: 2021/4/2 - 12:29
 * @Descripetion: Memento
 **/
public class Caretaker {

    private Memento memento;

    public Memento getMemento() {
        return this.memento;
    }

    public void setMemento(Memento memento) {
        this.memento = memento;
    }
}
  • Originator
package com.cz.Adaptermode.memento;

/**
 * @Author: zhang
 * @Date: 2021/4/2 - 12:31
 * @Descripetion: Originator
 **/
public class Memento {

    private String state;

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

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }
}
  • Caretaker
package com.cz.Adaptermode.memento;

/**
 * @Author: zhang
 * @Date: 2021/4/2 - 12:32
 * @Descripetion: Caretaker
 **/
public class Originator {

    private String state;

    public String getState() {
        return state;
    }

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

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

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

    public void showState(){
        System.out.println(state);
    }
}
  • Test
package com.cz.Adaptermode.memento;

/**
 * @Author: zhang
 * @Date: 2021/4/2 - 12:35
 * @Descripetion: Test
 **/
public class Test {
    public static void main(String[] args) {
        Originator originator = new Originator();
        originator.setState("上班中");

        Caretaker caretaker = new Caretaker();
        //将数据封装在Caretaker
        caretaker.setMemento(originator.createMemento());

        originator.setState("摸鱼中");
        //显示
        originator.showState();

        //将数据重新导入
        originator.setMemento(caretaker.getMemento());
        originator.showState();
    }
}
  • 运行结果:
    在这里插入图片描述

观察者模式

一、概述

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

二、适用性

  • 当一个抽象模型有两个方面,其中一个方面依赖于另一方面。 将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。
  • 当对一个对象的改变需要同时改变其它对象,而不知道具体有多少对象有待改变。
  • 当一个对象必须通知其它对象,而它又不能假定其它对象是谁。

三、参与者

  • Subject目标) 目标知道它的观察者。可以有任意多个观察者观察同一个目标。 提供注册和删除观察者对象的接口。
  • Observer观察者) 为那些在目标发生改变时需获得通知的对象定义一个更新接口。
  • ConcreteSubject具体目标) 将有关状态存入各ConcreteObserver对象。 当它的状态发生改变时,向它的各个观察者发出通知。
  • ConcreteObserver具体观察者) 维护一个指向ConcreteSubject对象的引用。 存储有关状态,这些状态应与目标的状态保持一致。 实现Observer的更新接口以使自身状态与目标的状态保持一致

四、类图

在这里插入图片描述

五、示例

  • Subject
package com.cz.Adaptermode.observer;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author: zhang
 * @Date: 2021/4/2 - 12:42
 * @Descripetion: Subject
 **/
public abstract class Citizen {

    List pols;
    String help = "normal";

    public String getHelp() {
        return this.help;
    }

    public void setHelp(String help) {
        this.help = help;
    }

    abstract void sendMessage(String help);

    public void setPolicemen(){
        this.pols = new ArrayList();
    }

    public void register(Policeman policeman){
        this.pols.add(policeman);
    }

    public void unRegister(Policeman policeman){
        this.pols.remove(policeman);
    }
}
  • Observer
package com.cz.Adaptermode.observer;

/**
 * @Author: zhang
 * @Date: 2021/4/2 - 12:47
 * @Descripetion: Observer
 **/
public interface Policeman {
    void action(Citizen citizen);
}
  • ConcreteSubject
package com.cz.Adaptermode.observer;

/**
 * @Author: zhang
 * @Date: 2021/4/2 - 12:49
 * @Descripetion: ConcreteSubject
 **/
public class HuangPuCitizen extends Citizen {

    public HuangPuCitizen(Policeman policeman){
        setPolicemen();
        register(policeman);
    }

    @Override
    void sendMessage(String help) {
        setHelp(help);
        for (int i = 0; i < pols.size(); i++){
            Policeman policeman = (Policeman) pols.get(i);
            //通知警察行动
            policeman.action(this);
        }
    }
}
package com.cz.Adaptermode.observer;

/**
 * @Author: zhang
 * @Date: 2021/4/2 - 12:52
 * @Descripetion: ConcreteSubject
 **/
public class TianHeCitizen extends Citizen {

    public TianHeCitizen(Policeman policeman){
        setPolicemen();
        register(policeman);
    }

    @Override
    void sendMessage(String help) {
        setHelp(help);
        for (int i = 0; i < pols.size(); i++){
            Policeman policeman = (Policeman) pols.get(i);
            //通知警察行动
            policeman.action(this);
        }
    }
}
  • ConcreteObserver
package com.cz.Adaptermode.observer;

/**
 * @Author: zhang
 * @Date: 2021/4/2 - 12:54
 * @Descripetion: ConcreteObserver
 **/
public class HuangPuPoliceman implements Policeman {

    @Override
    public void action(Citizen citizen) {
        String help = citizen.getHelp();
        if (help.equals("normal")){
            System.out.println("一切正常, 不用出动");
        }
        if (help.equals("unnormal")){
            System.out.println("有犯罪行为, 黄埔警察出动!");
        }
    }
}
package com.cz.Adaptermode.observer;

/**
 * @Author: zhang
 * @Date: 2021/4/2 - 12:56
 * @Descripetion: ConcreteObserver
 **/
public class TianHePoliceman implements Policeman {

    @Override
    public void action(Citizen citizen) {
        String help = citizen.getHelp();
        if (help.equals("normal")){
            System.out.println("一切正常, 不用出动");
        }
        if (help.equals("unnormal")){
            System.out.println("有犯罪行为, 天河警察出动!");
        }
    }
}
  • Test
package com.cz.Adaptermode.observer;

/**
 * @Author: zhang
 * @Date: 2021/4/2 - 12:58
 * @Descripetion: Test
 **/
public class Test {
    public static void main(String[] args) {
        Policeman thpol = new TianHePoliceman();
        Policeman hppol = new HuangPuPoliceman();

        Citizen citizen = new HuangPuCitizen(hppol);
        citizen.sendMessage("unnormal");
        citizen.sendMessage("normal");

        System.out.println("======================");
        citizen = new TianHeCitizen(thpol);
        citizen.sendMessage("normal");
        citizen.sendMessage("unnormal");
    }
}

  • 运行结果:
    在这里插入图片描述

状态模式

一、概述

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并
被自动更新。

二、适用性

  • 一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为。
  • 一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。 这个状态通常用一个或多个枚举常量表示。 通常,有多个操作包含这一相同的条件结构。 State模式将每一个条件分支放入一个独立的类中。 这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。

三、适用性

  • Context定义客户感兴趣的接口。 维护一个ConcreteState子类的实例,这个实例定义当前状态。
  • State 定义一个接口以封装与Context的一个特定状态相关的行为。
  • ConcreteStatesubclasses 每一子类实现一个与Context的一个状态相关的行为。

四、类图

在这里插入图片描述

五、示例

  • Context
package com.cz.Adaptermode.state;

/**
 * @Author: zhang
 * @Date: 2021/4/2 - 13:14
 * @Descripetion: Context
 **/
public class Context {

    private Weather weather;

    public Weather getWeather() {
        return this.weather;
    }

    public void setWeather(Weather weather) {
        this.weather = weather;
    }

    public String weatherMessage(){
        return weather.getWeather();
    }
}
  • State
package com.cz.Adaptermode.state;

/**
 * @Author: zhang
 * @Date: 2021/4/2 - 13:17
 * @Descripetion: State
 **/
public interface Weather {
    String getWeather();
}
  • ConcreteStatesubclasses
package com.cz.Adaptermode.state;

/**
 * @Author: zhang
 * @Date: 2021/4/2 - 13:18
 * @Descripetion: ConcreteStatesubclasses
 **/
public class Rain implements Weather {

    @Override
    public String getWeather() {
        return "下雨了";
    }
}
package com.cz.Adaptermode.state;

/**
 * @Author: zhang
 * @Date: 2021/4/2 - 13:18
 * @Descripetion: ConcreteStatesubclasses
 **/
public class Sunshine implements Weather{


    @Override
    public String getWeather() {
        return "出太阳了";
    }
}
  • Test
package com.cz.Adaptermode.state;

/**
 * @Author: zhang
 * @Date: 2021/4/2 - 13:19
 * @Descripetion: Test
 **/
public class Test {
    public static void main(String[] args) {
        Context context = new Context();
        context.setWeather(new Sunshine());
        System.out.println(context.weatherMessage());

        System.out.println("===============");

        Context context1 = new Context();
        context1.setWeather(new Rain());
        System.out.println(context1.weatherMessage());
    }
}
  • 运行结果:
    在这里插入图片描述

策略模式

一、概述

定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。

二、适用性

  • 许多相关的类仅仅是行为有异。“策略”提供了一种用多个行为中的一个行为来配置一个类的方法。
  • 需要使用一个算法的不同变体。
  • 算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的、与算法相关的数据结构。
  • 一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现。 将相关的条件分支移入它们各自的Strategy类中以代替这些条件语句。

三、参与者

  • Strategy 定义所有支持的算法的公共接口。Context使用这个接口来调用某ConcreteStrategy定义的算法。
  • ConcreteStrategyStrategy接口实现某具体算法。
  • Context用一个ConcreteStrategy对象来配置。 维护一个对Strategy对象的引用。 可定义一个接口来让Stategy访问它的数据

四、类图

在这里插入图片描述

五、示例

  • Strategy
package com.cz.Adaptermode.strategy;

/**
 * @Author: zhang
 * @Date: 2021/4/2 - 13:25
 * @Descripetion: Strategy
 **/
public abstract class Strategy {

    public abstract void method();
}
  • ConcreteStrategy
package com.cz.Adaptermode.strategy;

/**
 * @Author: zhang
 * @Date: 2021/4/2 - 13:27
 * @Descripetion: ConcreteStrategy
 **/
public class StrategyImplA extends Strategy {

    @Override
    public void method() {
        System.out.println("这是第一个实现");
    }
}
package com.cz.Adaptermode.strategy;

/**
 * @Author: zhang
 * @Date: 2021/4/2 - 13:29
 * @Descripetion: ConcreteStrategy
 **/
public class StrategyImplB extends Strategy {

    @Override
    public void method() {
        System.out.println("这是第二个实现");
    }
}
package com.cz.Adaptermode.strategy;

/**
 * @Author: zhang
 * @Date: 2021/4/2 - 13:30
 * @Descripetion: ConcreteStrategy
 **/
public class StrategyImplC extends Strategy {
    
    @Override
    public void method() {
        System.out.println("这是第三个实现");
    }
}
  • Context
package com.cz.Adaptermode.strategy;

/**
 * @Author: zhang
 * @Date: 2021/4/2 - 13:32
 * @Descripetion: Context
 **/
public class Context {

    Strategy strategy;

    public Context(Strategy strategy){
        this.strategy = strategy;
    }

    public void doMethod(){
        strategy.method();
    }
}

  • Test
package com.cz.Adaptermode.strategy;

/**
 * @Author: zhang
 * @Date: 2021/4/2 - 13:34
 * @Descripetion: Test
 **/
public class Test {
    public static void main(String[] args) {
        Context context = new Context(new StrategyImplA());
        context.doMethod();

        context = new Context(new StrategyImplB());
        context.doMethod();
        
        context = new Context(new StrategyImplC());
        context.doMethod();
    }
}

  • 运行结果:
    在这里插入图片描述

模板方法

一、概述

定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。 TemplateMethod使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

二、适用性

  • 一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。
  • 各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。 首先识别现有代码中的不同之处,并且将不同之处分离为新的操作。 最后,用一个调用这些新的操作的模板方法来替换这些不同的代码。
  • 控制子类扩展。

三、参与者

  • AbstractClass定义抽象的原语操作(primitiveoperation),具体的子类将重定义它们以实现一个算法的各步骤。 实现一个模板方法,定义一个算法的骨架。 该模板方法不仅调用原语操作,也调用定义在AbstractClass或其他对象中的操作。
  • ConcreteClass实现原语操作以完成算法中与特定子类相关的步骤。

四、类图

在这里插入图片描述

五、示例

  • AbstractClass
package com.cz.Adaptermode.template;

/**
 * @Author: zhang
 * @Date: 2021/4/2 - 13:38
 * @Descripetion: AbstractClass
 **/
public abstract class Template {

    public abstract void print();

    public void update(){
        System.out.println("开始打印");
        for (int i = 0; i < 10; i++){
            print();
        }
    }
}
  • ConcreteClass
package com.cz.Adaptermode.template;

/**
 * @Author: zhang
 * @Date: 2021/4/2 - 13:40
 * @Descripetion: ConcreteClass
 **/
public class TemplateConcrete extends Template {
    
    @Override
    public void print() {
        System.out.println("这是子类的实现");
    }
}
  • Test
package com.cz.Adaptermode.template;

/**
 * @Author: zhang
 * @Date: 2021/4/2 - 13:41
 * @Descripetion: Test
 **/
public class Test {
    public static void main(String[] args) {
        Template template = new TemplateConcrete();
        template.update();
    }
}
  • 运行结果:
    在这里插入图片描述

访问者模式

一、概述

表示一个作用于某对象结构中的各元素的操作。 它使你可以在不改变各元素的类的前提下定义作用于这
些元素的新操作。

二、适用性

  • 一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作。
  • 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而你想避免让这些操作“污染”这些对象的类。 Visitor使得你可以将相关的操作集中起来定义在一个类中。 当该对象结构被很多应用共享时,用Visitor模式让每个应用仅包含需要用到的操作。
  • 定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。 改变对象结构类需要重定义对所有访问者的接口,这可能需要很大的代价。 如果对象结构类经常改变,那么可能还是在这些类中定义这些操作较好。

三、参与者

  • Visitor 为该对象结构中ConcreteElement的每一个类声明一个Visit操作。 该操作的名字和特征标识了发送Visit请求给该访问者的那个类。 这使得访问者可以确定正被访问元素的具体的类。 这样访问者就可以通过该元素的特定接口直接访问它。
  • ConcreteVisitor实现每个由Visitor声明的操作。 每个操作实现本算法的一部分,而该算法片断乃是对应于结构中对象的类。 ConcreteVisitor为该算法提供了上下文并存储它的局部状态。 这一状态常常在遍历该结构的过程中累积结果。
  • Element定义一个Accept操作,它以一个访问者为参数。
  • ConcreteElement 实现Accept操作,该操作以一个访问者为参数。
  • ObjectStructure 能枚举它的元素。 可以提供一个高层的接口以允许该访问者访问它的元素。 可以是一个复合或是一个集合,如一个列表或一个无序集合。

四、类图

在这里插入图片描述

五、示例

  • Visitor
package com.cz.Adaptermode.visitor;

import java.util.Collection;

/**
 * @Author: zhang
 * @Date: 2021/4/2 - 13:46
 * @Descripetion: visitor
 **/
public interface Visitor {

    public void visitString(StringElement stringE);
    
    public void visitFloat(FloatElement floatE); 
    
    public void visitCollection(Collection collection);
}
  • ConcreteVisitor
package com.cz.Adaptermode.visitor;

import java.util.Collection;
import java.util.Iterator;

/**
 * @Author: zhang
 * @Date: 2021/4/2 - 13:47
 * @Descripetion: ConcreteVisitor
 **/
public class ConcreteVisitor implements Visitor {

    @Override
    public void visitString(StringElement stringE) {
        System.out.println(stringE.getSe());
    }

    @Override
    public void visitFloat(FloatElement floatE) {
        System.out.println(floatE.getFe());
    }

    @Override
    public void visitCollection(Collection collection) {
        Iterator iterator = collection.iterator();
        while (iterator.hasNext()){
            Object o = iterator.next();
            if (o instanceof Visitable){
                ((Visitable)o).accept(this);
            }
        }
    }
}
  • Element
package com.cz.Adaptermode.visitor;

/**
 * @Author: zhang
 * @Date: 2021/4/2 - 13:51
 * @Descripetion: Element
 **/
public interface Visitable {

    public void accept(Visitor visitor);
}
  • ConcreteElement
package com.cz.Adaptermode.visitor;

/**
 * @Author: zhang
 * @Date: 2021/4/2 - 13:53
 * @Descripetion: ConcreteElement
 **/
public class FloatElement implements Visitable {

    private Float fe;

    public FloatElement(Float fe){
        this.fe = fe;
    }

    public Float getFe(){
        return this.fe;
    }

    @Override
    public void accept(Visitor visitor) {
        visitor.visitFloat(this);
    }
}
package com.cz.Adaptermode.visitor;

import com.cz.Adaptermode.strategy.Strategy;

/**
 * @Author: zhang
 * @Date: 2021/4/2 - 13:55
 * @Descripetion: ConcreteElement
 **/
public class StringElement implements Visitable {

    private String se;

    public StringElement(String se){
        this.se = se;
    }

    public String getSe(){
        return this.se;
    }

    @Override
    public void accept(Visitor visitor) {
        visitor.visitString(this);
    }
}

  • Test
package com.cz.Adaptermode.visitor;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author: zhang
 * @Date: 2021/4/2 - 13:57
 * @Descripetion: Test
 **/
public class Test {
    public static void main(String[] args) {
        Visitor visitor = new ConcreteVisitor();
        StringElement se = new StringElement("abc");
        se.accept(visitor);

        FloatElement fe = new FloatElement(new Float(1.5));
        fe.accept(visitor);
        System.out.println("=============================");
        List result = new ArrayList();
        result.add(new StringElement("abc"));
        result.add(new StringElement("abc"));
        result.add(new StringElement("abc"));
        result.add(new FloatElement(new Float(1.5)));
        result.add(new FloatElement(new Float(1.5)));
        result.add(new FloatElement(new Float(1.5)));
        visitor.visitCollection(result);
    }
}

  • 运行结果:
    在这里插入图片描述

Java的23种设计模式到这就写完了。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值