结合JDK,Spring,Mybatis,Netty,Tomcat,Dubbo等经典框架的源码对设计模式展开分析(十一)

本文深入探讨了设计模式中的迭代器、命令、状态、备忘录、中介者、解析器和观察者模式,通过JDK源码和经典框架如Spring、Mybatis等的应用,阐述了这些模式的核心概念、优缺点及实际场景。通过学习,可以提升对设计模式的理解和在项目中的应用能力。
摘要由CSDN通过智能技术生成
  • 迭代器模式(Iterator Pattern)

定义:又叫做游标模式,它提供一种按顺序访问集合对象元素的方法,可以用来为不同的容器提供一致的遍历行为

本质时把集合对象的迭代行为抽象到迭代器中,提供统一的访问接口,而不用关心容器内元素的组成结构

应用场景:访问一个集合对象的内容而无需暴露它的内容表示,为遍历不同发集合结构提供一个同一个访问接口

角色:抽象迭代器,具体迭代器,抽象容器,具体容器

通用写法:

package com.IteratorPattern;

/**
 * @author yangxiaozhen
 * @date 2022/5/21-15:41
 */
public interface Iterator<E> {
    E next();
    boolean hasNext();
}
package com.IteratorPattern;

import java.util.List;

/**
 * @author yangxiaozhen
 * @date 2022/5/21-15:46
 */
public class ConcreteIterator<E> implements Iterator {
    private List<E> list;
    private int cursor = 0;

    public ConcreteIterator(List<E> list) {
        this.list = list;
    }

    @Override
    public Object next() {
        return this.list.get(cursor + 1);
    }

    @Override
    public boolean hasNext() {
        return this.cursor < this.list.size();
    }
}
package com.IteratorPattern;

/**
 * 具体容器
 * @author yangxiaozhen
 * @date 2022/5/21-15:42
 */
public interface IAggregate<E> {
    boolean add(E e);

    boolean remove(E e);

    Iterator iterator();
}

 

package com.IteratorPattern;

import java.util.List;

/**
 * @author yangxiaozhen
 * @date 2022/5/21-16:20
 */
public class IAggregateImpl<E> implements IAggregate<E> {
    private List<E> list;

    public IAggregateImpl(List<E> list) {
        this.list = list;
    }

    @Override
    public boolean add(E e) {
        return this.list.add(e);
    }

    @Override
    public boolean remove(E e) {
        return this.list.remove(e);
    }

    @Override
    public Iterator iterator() {
        return new ConcreteIterator<E>(this.list);
    }
}

迭代模式在JDK源码中的应用:

ArrayList,Vector等集合集合对象中基本都有的一个内部实现类Itr实现Iterator,类似的实现方式在JDK和框架中非常常见,就不意义列举了

优点:多态迭代,简化集合对象接口,迭代方式多样化,解耦迭代和集合

缺点:日常开发中几乎不会使用到,触发自定义数据结构,否则开源框架提供的API完全够用

  • 命令模式(Command Pattern)

定义:命令模式是对命令的封装,通过在请求与实现间引入一个抽象命令接口,

解耦命令的请求方和接收方,是命令具有扩展性,中间件是抽象的

应用场景:实现语义中具备命令的操作入shell命令,解耦请求方和接收方,使得两者不直接交互

角色:接收者,抽象命令,具体命令,请求者

通用实现:

package com.CommandPattern;

/**
 * @author yangxiaozhen
 * @date 2022/5/22-12:06
 */
public class Computer {
    void startComputer(){
        System.out.println("电脑开机");
    }
    void stopComputer(){
        System.out.println("电脑关机");
    }
}

 

package com.CommandPattern;

/**
 * @author yangxiaozhen
 * @date 2022/5/22-12:07
 */
public class Door {
    void openDoor(){
        System.out.println("打开房门");
    }
    void CloseDoor(){
        System.out.println("关闭房门");
    }
}
package com.CommandPattern;

/**
 * @author yangxiaozhen
 * @date 2022/5/22-12:06
 */
public class Light {
    void on(){
        System.out.println("开灯");
    }
    void off(){
        System.out.println("关灯");
    }
}

 

package com.CommandPattern;

/**
 * @author yangxiaozhen
 * @date 2022/5/22-12:10
 */
public interface Command {
    void execute();
}

package com.CommandPattern;

/**
 * @author yangxiaozhen
 * @date 2022/5/22-12:11
 */
public class CommandImpl1 implements Command {
    private Light light;
    private Computer computer;
    private Door door;
    @Override
    public void execute() {
        door.openDoor();
        computer.startComputer();
        light.on();
    }

    public CommandImpl1(Light light, Computer computer, Door door) {
        this.light = light;
        this.computer = computer;
        this.door = door;
    }

    public static void main(String[] args) {
        //客户端调用命令对象,当命令进行扩展或底层如电脑之类的实体进行拓展时,不会影响客户端之前的代码
        new CommandImpl1(new Light(),new Computer(),new Door()).execute();
    }
}

在JDK源码中的应用:

Runnable接口,相当于是命令的抽象,实际上调用线程的start()方法后,就有资格去抢CPU资源,而不需要编写获取CPU资源,Runnable充当了调用者和执行者之间的中间件

优点:引入抽象接口作为中间件,解耦了命令请求和实现,扩展性良好,可以组合其他设计模式来使用,更加灵活

缺点:具体命令类可能过多。

  • 状态模式(State Pattern)

定义:又叫状态机模式,允许对象在内部状态发生改变时改变他的行为。

类的行为由状态决定,意图让一个对象在其内部改变的时候,行为也随之改变。

应用场景:在软件开发中,对于某一种操作存在不同的情况时,通常最直接的方式就是使用if...elsr等条件判断语句进行穷举,这些的代码看起来过于臃肿,可读性差,且不具备扩展性

角色:上下文角色,抽象状态角色,具体状态角色

与策略模式的区别:从类结构上看,其架构几乎完全一样,但是两者的应用场景存在差别,策略模式中,每种策略相互独立,策略的选择由客户端去抉择,而状态模式的各各状态之间存在相互关系,彼此之间存在一定条件下的相互转换关系,我理解的状态模式实际上是策略模式的特殊形式,是延申的形式,也就是策略模式中,各各策略存在某种转换关系,并且转换的操作由策略类自己来进行

游戏角色业务场景模拟使用状态模式:

package com.StatePattern;

/**
 * @author yangxiaozhen
 * @date 2022/5/22-14:57
 */
public interface IRoleState {
    void jump(Role role);
    void crouch(Role role);
    void aHead(Role role);
    void retreat(Role role);
}

 

package com.StatePattern;

/**
 * @author yangxiaozhen
 * @date 2022/5/22-15:05
 */
public class AirIRoleStateImpl implements IRoleState {
    @Override
    public void jump(Role role) {
        System.out.println("空中不可跳跃");
    }

    @Override
    public void crouch(Role role) {
        System.out.println("空中变为站立状态");
        role.setCurrentState(Role.ROLE_STATE_STAND);
    }

    @Override
    public void aHead(Role role) {
        System.out.println("空中不可前进");
    }

    @Override
    public void retreat(Role role) {
        System.out.println("空中不可后退");
    }
}
package com.StatePattern;

/**
 * @author yangxiaozhen
 * @date 2022/5/22-15:13
 */
public class CrouchIRoleStateImpl implements IRoleState {
    @Override
    public void jump(Role role) {
        System.out.println("下蹲跳跃变为站立状态");
        role.setCurrentState(Role.ROLE_STATE_STAND);
    }

    @Override
    public void crouch(Role role) {
        System.out.println("下蹲不可重复下蹲");
    }

    @Override
    public void aHead(Role role) {
        System.out.println("下蹲状态不可前进");
    }

    @Override
    public void retreat(Role role) {
        System.out.println("下蹲状态不可后退");
    }
}

 

package com.StatePattern;

/**
 * @author yangxiaozhen
 * @date 2022/5/22-15:09
 */
public class StandIRoleStateImpl implements IRoleState {
    @Override
    public void jump(Role role) {
        System.out.println("站立状态跳跃变为空中状态");
        role.setCurrentState(Role.ROLE_STATE_AIR);
    }

    @Override
    public void crouch(Role role) {
        System.out.println("站立状态下蹲变为下蹲状态");
        role.setCurrentState(Role.ROLE_STATE_CROUCH);
    }

    @Override
    public void aHead(Role role) {
        System.out.println("前进");
    }

    @Override
    public void retreat(Role role) {
        System.out.println("后退");
    }
}
package com.StatePattern;

/**
 * @author yangxiaozhen
 * @date 2022/5/22-15:14
 */
public class Role {
    public static final IRoleState ROLE_STATE_AIR = new AirIRoleStateImpl();
    public static final IRoleState ROLE_STATE_STAND = new StandIRoleStateImpl();
    public static final IRoleState ROLE_STATE_CROUCH = new CrouchIRoleStateImpl();

    private IRoleState currentState;

    public Role() {
        this.currentState = ROLE_STATE_STAND;
    }

    public IRoleState getCurrentState() {
        return currentState;
    }

    public void setCurrentState(IRoleState currentState) {
        this.currentState = currentState;
    }

    public void jump() {
        currentState.jump(this);
    }


    public void crouch() {
        currentState.crouch(this);
    }


    public void aHead() {
        currentState.aHead(this);
    }


    public void retreat() {
        currentState.retreat(this);
    }
}

 

优点:将状态独立为类,消除了冗余的if...else switch...case语句,使得代码的扩展性提高

缺点:类膨胀。

  • 备忘录模式(Memento Pattern)

定义:又叫作快照模式,指在不破坏封装的前提下,捕获一个对象的内部状态,并在对象之外保存这个状态,在需要复原的时候可以复原回来

应用场景:需要保存历史快照的场景

这种模式实用性不强,简单来说就是相当于储存一个目标对象需要储存时的副本,类似以clone或序列化,然后建立一个管理类储存(经常时集合对象)这些副本,当需要状态回退时,再根据需要的规则去取得状态对象,没什么好描述的

  • 中介者模式(Mediator Pattern)

定义:又叫做调解者模式或调停者模式,用一个中介者对象封装一系列的交互对象,解耦他们之间的交互,简单来说就是由一个中介者对象来管理所有对象的交互。

角色:抽象中介者,具体中介者,抽象同事类,具体同事类

通用写法:

package com.MediatorPattern;

/**
 * @author yangxiaozhen
 * @date 2022/5/22-19:47
 */
public class User {
    private String name;
    private ChatRoom chatRoom;

    public User(String name, ChatRoom chatRoom) {
        this.name = name;
        this.chatRoom = chatRoom;
    }

    public void sendMessage(String s) {
        this.chatRoom.showMsg(this,s);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public ChatRoom getChatRoom() {
        return chatRoom;
    }

    public void setChatRoom(ChatRoom chatRoom) {
        this.chatRoom = chatRoom;
    }
}
package com.MediatorPattern;

/**
 * @author yangxiaozhen
 * @date 2022/5/22-19:48
 */
public class ChatRoom {
    public  void showMsg(User user,String msg){
        System.out.println("["+user.getName()+"]:"+msg);
    }

    public static void main(String[] args) {
        ChatRoom chatRoom = new ChatRoom();
        User tom = new User("Tom", chatRoom);
        tom.sendMessage("Im Tom");

    }
}

 

优点:减少类间的耦合,将多对多关系转为一对多关系

缺点:其实就是将原先多个对象之间的相互依赖转化为了中介者的集中依赖,于是当同事类越来越多时,中介者就会越来越臃肿,难以维护

  • 解析器模式(Interpreter Pattern)

定义:是一种按照规定的语法进行解析的模式,就比如编译器将源码解释为机器码,让CPU能够识别和运行

应用场景:其实这个模式非常普遍,普遍到我们根本意识不到,比如“一千个人心中有一千个哈姆雷特”,我们每个人都像是持有一个解析器一样,再比如摩斯密码,正则匹配等

角色:解析器主要分为终结符表达式和非终结符表达式:B+C=A中=是终结符;+号是非终结符。

JDK中的应用:

Pattern对正则表达式的编译和解析

日常开发中关于解析器模式的使用并不常用,就不加以研究了,简单点说就是定义一个对象专门处理逻辑关系的匹配,将输入的对象匹配成另一只需要的对象,就像是封装了if...else一样。

  • 观察者模式(Observer Pattern)

定义:又叫作发布-订阅模式,定义一种一对多的依赖关系,一个主题对象可被多个观察者对象同时监听,使得主题对象状态变化时,所依赖它的对象都会得到通知并被自动更新

核心是将观察者与被观察者解耦,以一种类似消息/广播发送的机制联动两者,使被观察者的变动能通知到感兴趣的观察者们

应用场景:应用场景相当广泛,在软件系统中,当系统一方行为依赖另一方行为的变动时,可使用观察者模式松耦合双方

角色:抽象主题,具体主题,抽象观察者,具体观察者

通用实现:

package com.ObserverPattern;

/**
 * @author yangxiaozhen
 * @date 2022/5/22-21:47
 */
public interface IObserver {
    void update();

    interface ISubject {
        boolean add(IObserver observer);
        boolean detach(IObserver observer);
        void Inotify();
    }
}
package com.ObserverPattern;

/**
 * @author yangxiaozhen
 * @date 2022/5/22-21:56
 */
public class MyObserver implements  IObserver {
    @Override
    public void update() {
        System.out.println("收到通知");
    }
}
package com.ObserverPattern;


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

/**
 * @author yangxiaozhen
 * @date 2022/5/22-21:51
 */
public class MySubject implements IObserver.ISubject {
    private List<IObserver> observers = new ArrayList<IObserver>();

    @Override
    public boolean add(IObserver observer) {
        return observers.add(observer);
    }

    @Override
    public boolean detach(IObserver observer) {
        return observers.remove(observer);
    }

    @Override
    public void Inotify() {
        for (IObserver observer : observers) {
            observer.update();
        }
    }

    public static void main(String[] args) {
        MyObserver myObserver = new MyObserver();
        MySubject mySubject = new MySubject();
        mySubject.add(myObserver);
        mySubject.Inotify();
    }
}

也可以基于JDK-Observable,Observer实现通知机制

也可以基于Guava API实现

各种框架中应用非常广泛

优点:观察者与被观察者松耦合,实现一对多的通信机制,支持事件触发机制

缺点:事件通知呈线性关系,如果其中一个观察者处理事件卡壳,则会影响后湖的观察者接受该事件

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值