设计模式——十一种行为型模式(Java&Golang实现)

本文📚深入探讨了十一种行为型设计模式,如策略🎯、观察者👀和命令模式⚙️。每种模式均阐述了其目标🎯、适用场景🌍及案例分析🔍,并提供Java和Go语言的代码实现💻。这为软件开发者提供了理论与实践结合的宝贵资源🌟,帮助他们优化代码结构🛠️,提升软件的可维护性和灵活性,是理论与实战相结合的典范🏆。

设计模式——五种创建型模式(Java&Golang实现)

设计模式——七种结构型模式(Java&Golang实现)

行为型模式(Behavioral Patterns)

关注对象之间的责任分配,象之间如何通信、协作以完成特定任务,主要解决的是对象之间的责任分配和协作。

1、观察者模式(Observer)

  • 目的:定义一种对象间的一对多的依赖关系,使得当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
  • 应用场景:一个对象的改变需要同时改变其他对象,并且不知道具体有多少对象需要改变时;一个对象应该能够通知其他对象,而不需要知道这些对象是谁时;一个抽象模型有两个方面,其中一个方面依赖于另一个方面,但是两者又可以独立变化时。
  • 案例:一个新闻订阅系统,新闻站点是被观察的主题,而订阅者是观察者。当新闻站点发布新的新闻时,所有订阅者都会收到通知并更新。
  • 结构图:

img

Java实现

// Subject.java
// 订阅系统接口
interface Subject {
    void addObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers(String news);
}

// NewsStation.java
// 新闻主题
class NewsStation implements Subject {
    private List<Observer> observers = new ArrayList<>();
    private String latestNews;

    public void setLatestNews(String news) {
        this.latestNews = news;
        notifyObservers(news);
    }

    @Override
    public void addObserver(Observer observer) {
        observers.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    @Override
    public void notifyObservers(String news) {
        for (Observer item : observers) {
            item.update(news);
        }
    }
}

// Observer.java
// 观察者接口
interface Observer {
    void update(String news);
}

// Subscriber.java
// 具体观察者
class Subscriber implements Observer {
    private final String name;

    public Subscriber(String name) {
        this.name = name;
    }

    @Override
    public void update(String news) {
        System.out.println(name + " 接受到最新的消息: " + news);
    }
}

// Main.java
// 客户端
public class Main {
    public static void main(String[] args) {
        // 创建新闻站
        NewsStation newsStation = new NewsStation();

        // John注册
        Observer subscriber1 = new Subscriber("John");
        // Alice注册
        Observer subscriber2 = new Subscriber("Alice");

        // John订阅新闻
        newsStation.addObserver(subscriber1);
        // Alice订阅新闻
        newsStation.addObserver(subscriber2);

        // 模拟新闻发布
        newsStation.setLatestNews("今年除夕不放假");

        // Alice取消订阅
        newsStation.removeObserver(Alice);
        // 模拟新闻发布
        newsStation.notifyObservers("2、除夕一起包饺子");
    }
}

golang实现

package main

import (
    "fmt"
    "sync"
)

// 定义被观察者接口
type Subject interface {
    addObserver(observer Observer) error
    removeObserver(id string) error
    notifyObservers(news string)
}

// 定义观察者接口
type Observer interface {
    update(news string)
}


type NewsStation struct {
    mutex      sync.Mutex
    observers  map[string]Observer
    latestNews string
}

func NewNewsStation() *NewsStation {
    return &NewsStation{
        observers: make(map[string]Observer),
    }
}

func (n *NewsStation) addObserver(observer Observer, id string) error {
    n.mutex.Lock()
    defer n.mutex.Unlock()
    if _, exists := n.observers[id]; exists {
        return fmt.Errorf("id 为 '%s' 已存在", id)
    }
    n.observers[id] = observer
    return nil
}

func (n *NewsStation) removeObserver(id string) error {
    n.mutex.Lock()
    defer n.mutex.Unlock()
    if _, exists := n.observers[id]; !exists {
        return fmt.Errorf("id 为 '%s' 不存在", id)
    }
    delete(n.observers, id)
    return nil
}

func (n *NewsStation) notifyObservers(news string) {
    n.mutex.Lock()
    defer n.mutex.Unlock()

    for _, observer := range n.observers {
        observer.update(news)
    }
}

// 观察者
type Subscriber struct {
    name string
}

func NewSubscriber(name string) *Subscriber {
    return &Subscriber{name: name}
}

func (s *Subscriber) update(news string) {
    fmt.Printf("%s 接受到最新的消息: %s\n", s.name, news)
}

func main() {
    // 新闻站
    newsStation := NewNewsStation()

    // john注册
    john := NewSubscriber("john")
    // alice注册
    alice := NewSubscriber("alice")

    // john关注新闻站
    newsStation.addObserver(john, "john")
    // alice关注新闻站
    newsStation.addObserver(alice, "alice")

    // 新闻站发送第一条消息
    newsStation.notifyObservers("1、今年除夕不放假")

    // alice取消关注新闻站
    newsStation.removeObserver("alice")

    // 新闻站发送第二条消息
    newsStation.notifyObservers("2、除夕一起包饺子")

}

2、策略模式(Strategy)

  • 目的:定义一系列算法,将每个算法封装起来,并使它们可以相互替换。客户端可以独立于具体的算法,并且可以轻松地切换算法,从而实现灵活的行为变化。
  • 应用场景:当一个系统中有多个算法,且需要在运行时动态选择其中之一时,策略模式是一个合适的选择;当一个类有多个条件语句来选择不同的行为时,可以考虑使用策略模式来替代条件语句,提高可维护性;当不希望客户端依赖于具体算法实现,而是希望算法可以独立变化时,策略模式是一个有效的设计方案。
  • 案例:个图像处理应用,其中有多种滤镜算法可以选择,例如黑白滤镜、模糊滤镜和反转色彩滤镜。使用策略模式可以使用户在运行时选择并切换不同的滤镜算法。
  • 结构图:

img

Java实现

// ImageFilter.java
// 策略接口
interface ImageFilter {
    void applyFilter(String imageName);
}

// BlackAndWhiteFilter.java
// 具体策略 - 黑白滤镜
class BlackAndWhiteFilter implements ImageFilter {
    @Override
    public void applyFilter(String imageName) {
        System.out.println("使用黑白滤镜 " + imageName);
    }
}

// BlurFilter.java
// 具体策略 - 模糊滤镜
class BlurFilter implements ImageFilter {
    @Override
    public void applyFilter(String imageName) {
        System.out.println("使用模糊滤镜 " + imageName);
    }
}

// InvertColorFilter.java
// 具体策略 - 反转色彩滤镜
class InvertColorFilter implements ImageFilter {
    @Override
    public void applyFilter(String imageName) {
        System.out.println("使用反转色彩滤镜 " + imageName);
    }
}

// ImageProcessor.java
// 上下文
class ImageProcessor {
    private ImageFilter imageFilter;

    public void setImageFilter(ImageFilter imageFilter) {
        this.imageFilter = imageFilter;
    }

    public void processImage(String imageName) {
        imageFilter.applyFilter(imageName);
    }
}

// Main.java
// 客户端
public class Main {
    public static void main(String[] args) {
        ImageProcessor imageProcessor = new ImageProcessor();

        // 使用黑白滤镜
        imageProcessor.setImageFilter(new BlackAndWhiteFilter());
        imageProcessor.processImage("image1.jpg");

        // 切换为模糊滤镜
        imageProcessor.setImageFilter(new BlurFilter());
        imageProcessor.processImage("image2.jpg");

        // 切换为反转色彩滤镜
        imageProcessor.setImageFilter(new InvertColorFilter());
        imageProcessor.processImage("image3.jpg");
    }
}

golang实现

package main

import "fmt"

type ImageFilter interface {
	applyFilter(imageName string)
}

type BlackAndWhiteFilter struct{}

func (b *BlackAndWhiteFilter) applyFilter(imageName string) {
	fmt.Printf("使用黑白滤镜 %s\n", imageName)
}

type BlurFilter struct{}

func (b *BlurFilter) applyFilter(imageName string) {
	fmt.Printf("使用模糊滤镜 %s\n", imageName)
}

type InvertColorFilter struct{}

func (i *InvertColorFilter) applyFilter(imageName string) {
	fmt.Printf("使用反转色彩滤镜 %s\n", imageName)
}

type ImageProcessor struct {
	imageFilter ImageFilter
}

func (i *ImageProcessor) setImageFilter(imageFilter ImageFilter) {
	i.imageFilter = imageFilter
}

func (i *ImageProcessor) processImage(imageName string) {
	i.imageFilter.applyFilter(imageName)
}

func main() {
	imageProcessor := &ImageProcessor{}

	// 使用黑白滤镜
	imageProcessor.setImageFilter(&BlackAndWhiteFilter{})
	imageProcessor.processImage("image1.jpg")

	// 切换为模糊滤镜
	imageProcessor.setImageFilter(&BlurFilter{})
	imageProcessor.processImage("image2.jpg")

	// 切换为模糊滤镜
	imageProcessor.setImageFilter(&InvertColorFilter{})
	imageProcessor.processImage("image3.jpg")
}

3、命令模式(Command

  • 目的:将请求封装成对象,从而使得客户端可以参数化队列,延迟请求的执行,或者将请求与接收者对象解耦。
  • 应用场景:当希望将请求的发送者和接收者解耦时,可以使用命令模式。发送者不需要知道接收者的具体类,只需知道命令对象即可;当需要支持撤销(Undo)操作时,可以使用命令模式。每个命令对象可以存储执行前的状态,以便在需要时撤销操作。
  • 案例:一个简单的遥控器应用,遥控器可以控制多个设备(例如电视、音响)并支持撤销操作。每个设备的操作都被封装成命令对象,遥控器通过调用这些命令对象来实现控制。
  • 结构图:

img

Java实现

// 命令接口
interface Command {
    void execute();
    void undo();
}

// 具体命令 - 开启电视
class TurnOnTVCommand implements Command {
    private TV tv;

    public TurnOnTVCommand(TV tv) {
        this.tv = tv;
    }

    @Override
    public void execute() {
        tv.turnOn();
    }

    @Override
    public void undo() {
        tv.turnOff();
    }
}

// 具体命令 - 关闭电视
class TurnOffTVCommand implements Command {
    private TV tv;

    public TurnOffTVCommand(TV tv) {
        this.tv = tv;
    }

    @Override
    public void execute() {
        tv.turnOff();
    }

    @Override
    public void undo() {
        tv.turnOn();
    }
}

// 接收者 - 电视
class TV {
    void turnOn() {
        System.out.println("电视已开启");
    }

    void turnOff() {
        System.out.println("电视已关闭");
    }
}

// 调用者 - 遥控器
class RemoteControl {
    private Command command;

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

    public void pressButton() {
        command.execute();
    }

    public void pressUndoButton() {
        command.undo();
    }
}

// 客户端
public class CommandPatternExample {
    public static void main(String[] args) {
        TV tv = new TV();
        Command turnOnCommand = new TurnOnTVCommand(tv);
        Command turnOffCommand = new TurnOffTVCommand(tv);

        RemoteControl remoteControl = new RemoteControl();

        // 开启电视
        remoteControl.setCommand(turnOnCommand);
        remoteControl.pressButton();

        // 关闭电视
        remoteControl.setCommand(turnOffCommand);
        remoteControl.pressButton();

        // 撤销操作
        remoteControl.pressUndoButton();
    }
}

golang实现

package main

import "fmt"

type TV struct{}

func (tv *TV) turnOn() {
	fmt.Println("电视已开启")
}

func (tv *TV) turnOff() {
	fmt.Println("电视已关闭")
}

type Command interface {
	execute()
	undo()
}

type TurnOffTVCommand struct {
	tv TV
}

func (t *TurnOffTVCommand) execute() {
	t.tv.turnOff()
}

func (t *TurnOffTVCommand) undo() {
	t.tv.turnOn()
}

type TurnOnTVCommand struct {
	tv TV
}

func (t *TurnOnTVCommand) execute() {
	t.tv.turnOn()
}

func (t *TurnOnTVCommand) undo() {
	t.tv.turnOff()
}

type RemoteControl struct {
	command Command
}

func (r *RemoteControl) setCommand(command Command) {
	r.command = command
}

func (r *RemoteControl) pressButton() {
	r.command.execute()
}

func (r *RemoteControl) pressUndoButton() {
	r.command.undo()
}

func main() {
	tv := TV{}
	turnOnTVCommand := &TurnOnTVCommand{tv: tv}
	turnOffTVCommand := &TurnOffTVCommand{tv: tv}

	remoteControl := &RemoteControl{}

	// 开启电视机
	remoteControl.setCommand(turnOnTVCommand)
	remoteControl.pressButton()

	// 关闭电视机
	remoteControl.setCommand(turnOffTVCommand)
	remoteControl.pressButton()

	//撤销操作
	remoteControl.pressUndoButton()

}

4、状态模式(State

  • 目的:允许一个对象在其内部状态发生改变时改变其行为,使其看起来好像修改了其类。状态模式将对象的状态封装成不同的类,使得在切换状态时能够轻松地改变对象的行为。
  • 应用场景:当一个对象的行为取决于它的状态,并且需要在运行时根据状态改变行为时,可以使用状态模式; 当一个对象有很多状态,并且通过大量的条件语句来切换状态时,可以考虑使用状态模式来简化代码结构; 当对象的行为需要随着状态的变化而变化,而且状态之间有相互转换的关系时,使用状态模式可以使系统更加灵活。
  • 案例:一个自动售货机的例子,其中自动售货机有多个状态,例如投币状态、选择商品状态、出货状态等。不同状态下,自动售货机的行为会有所不同。

Java实现

// VendingMachineState.java
// 状态接口
interface VendingMachineState {
    void insertCoin();
    void selectProduct();
    void dispenseProduct();
}

// CoinInsertedState.java
// 具体状态 - 投币状态
class CoinInsertedState implements VendingMachineState {
    @Override
    public void insertCoin() {
        System.out.println("已投币");
    }

    @Override
    public void selectProduct() {
        System.out.println("产品选择");
    }

    @Override
    public void dispenseProduct() {
        System.out.println("请先选择产品");
    }
}

// ProductSelectedState.java
// 具体状态 - 选择商品状态
class ProductSelectedState implements VendingMachineState {
    @Override
    public void insertCoin() {
        System.out.println("已投币");
    }

    @Override
    public void selectProduct() {
        System.out.println("产品以选择");
    }

    @Override
    public void dispenseProduct() {
        System.out.println("产品分配");
    }
}

// 具体状态 - 出货状态
class ProductDispensedState implements VendingMachineState {
    @Override
    public void insertCoin() {
        System.out.println("请稍等,正在分配产品");
    }

    @Override
    public void selectProduct() {
        System.out.println("产品以选择");
    }

    @Override
    public void dispenseProduct() {
        System.out.println("产品已配发,谢谢!");
    }
}

// 上下文 - 自动售货机
class VendingMachine {
    private VendingMachineState currentState;

    public VendingMachine() {
        currentState = new CoinInsertedState();
    }

    public void setCurrentState(VendingMachineState state) {
        currentState = state;
    }

    public void insertCoin() {
        currentState.insertCoin();
    }

    public void selectProduct() {
        currentState.selectProduct();
    }

    public void dispenseProduct() {
        currentState.dispenseProduct();
    }
}

// 客户端
public class StatePatternExample {
    public static void main(String[] args) {
        VendingMachine vendingMachine = new VendingMachine();

        vendingMachine.insertCoin();
        vendingMachine.selectProduct();
        vendingMachine.dispenseProduct();
    }
}

golang实现

package main

import "fmt"

// 状态接口
type VendingMachineState interface {
	InsertCoin(vm *VendingMachine)
	SelectProduct(vm *VendingMachine)
	DispenseProduct(vm *VendingMachine)
}

// 具体状态 - 投币状态
type CoinInsertedState struct{}

func (c *CoinInsertedState) InsertCoin(vm *VendingMachine) {
	fmt.Println("已投币")
}

func (c *CoinInsertedState) SelectProduct(vm *VendingMachine) {
	fmt.Println("产品选择")
	vm.SetState(&ProductSelectedState{})
}

func (c *CoinInsertedState) DispenseProduct(vm *VendingMachine) {
	fmt.Println("请先选择产品")
}

// 具体状态 - 选择商品状态
type ProductSelectedState struct{}

func (p *ProductSelectedState) InsertCoin(vm *VendingMachine) {
	fmt.Println("已投币")
}

func (p *ProductSelectedState) SelectProduct(vm *VendingMachine) {
	fmt.Println("产品已选择")
}

func (p *ProductSelectedState) DispenseProduct(vm *VendingMachine) {
	fmt.Println("产品配发")
	vm.SetState(&ProductDispensedState{})
}

// 具体状态 - 出货状态
type ProductDispensedState struct{}

func (p *ProductDispensedState) InsertCoin(vm *VendingMachine) {
	fmt.Println("请稍等,正在分配产品")
}

func (p *ProductDispensedState) SelectProduct(vm *VendingMachine) {
	fmt.Println("产品已选择")
}

func (p *ProductDispensedState) DispenseProduct(vm *VendingMachine) {
	fmt.Println("产品已配发,谢谢!")
}

// 上下文 - 自动售货机
type VendingMachine struct {
	currentState VendingMachineState
}

func (vm *VendingMachine) SetState(state VendingMachineState) {
	vm.currentState = state
}

func (vm *VendingMachine) InsertCoin() {
	vm.currentState.InsertCoin(vm)
}

func (vm *VendingMachine) SelectProduct() {
	vm.currentState.SelectProduct(vm)
}

func (vm *VendingMachine) DispenseProduct() {
	vm.currentState.DispenseProduct(vm)
}

// 客户端
func main() {
	vendingMachine := &VendingMachine{currentState: &CoinInsertedState{}}

	vendingMachine.InsertCoin()
	vendingMachine.SelectProduct()
	vendingMachine.DispenseProduct()
}

5、责任链模式(Chain of Responsibility

  • 目的:将请求的发送者和接收者解耦,并且使多个对象都有机会处理这个请求。责任链模式形成一条链,每个对象在收到请求后都会决定是否处理,以及是否将请求传递给下一个对象。
  • 应用场景:当请求的发送者不需要知道请求被谁处理,以及处理的具体细节时,可以使用责任链模式; 当希望多个对象都有机会处理同一个请求时,可以使用责任链模式;当希望动态地指定处理流程时,可以使用责任链模式。通过动态地调整处理者之间的连接关系,可以实现灵活的处理流程。
  • 案例:一个审批流程的例子,假设一个请假申请需要经过多个领导层级的审批。不同级别的领导可以是责任链中的不同处理者,每个领导负责判断是否能够批准该请假申请,如果不能,则将请求传递给下一级领导。
  • 结构图

img

Java实现

// LeaveRequest.java
// 请求类
class LeaveRequest {
    private String employee;
    private int days;

    public LeaveRequest(String employee, int days) {
        this.employee = employee;
        this.days = days;
    }

    public String getEmployee() {
        return employee;
    }

    public int getDays() {
        return days;
    }
}

// Approver.java
// 处理者接口
interface Approver {
    void processRequest(LeaveRequest request);
}

// Supervisor.java
// 具体处理者 - 直接主管
class Supervisor implements Approver {
    private Approver nextApprover;

    public void setNextApprover(Approver nextApprover) {
        this.nextApprover = nextApprover;
    }

    @Override
    public void processRequest(LeaveRequest request) {
        if (request.getDays() <= 2) {
            System.out.println("主管批准的员工休假申请: " + request.getEmployee());
        } else if (nextApprover != null) {
            nextApprover.processRequest(request);
        } else {
            System.out.println("主管未批准的员工休假申请: " + request.getEmployee());
        }
    }
}

// DepartmentManager.java
// 具体处理者 - 部门经理
class DepartmentManager implements Approver {
    private Approver nextApprover;

    public void setNextApprover(Approver nextApprover) {
        this.nextApprover = nextApprover;
    }

    @Override
    public void processRequest(LeaveRequest request) {
        if (request.getDays() <= 5) {
            System.out.println("部门经理批准的员工休假申请: " + request.getEmployee());
        } else if (nextApprover != null) {
            nextApprover.processRequest(request);
        } else {
            System.out.println("部门经理未批准的员工休假申请: " + request.getEmployee());
        }
    }
}

// GeneralManager.java
// 具体处理者 - 总经理
class GeneralManager implements Approver {
    @Override
    public void processRequest(LeaveRequest request) {
        if (request.getDays() > 5) {
            System.out.println("总经理批准的员工休假申请: " + request.getEmployee());
        } else {
            System.out.println("总经理未批准的员工休假申请: " + request.getEmployee());
        }
    }
}

// Main.java
// 客户端
public class Main {
    public static void main(String[] args) {
        // 创建处理者对象
        Supervisor supervisor = new Supervisor();
        DepartmentManager departmentManager = new DepartmentManager();
        GeneralManager generalManager = new GeneralManager();

        // 设置处理者之间的关系
        supervisor.setNextApprover(departmentManager);
        departmentManager.setNextApprover(generalManager);

        // 创建请假请求
        LeaveRequest request1 = new LeaveRequest("John", 1);
        LeaveRequest request2 = new LeaveRequest("Alice", 3);
        LeaveRequest request3 = new LeaveRequest("Bob", 7);

        // 处理请假请求
        supervisor.processRequest(request1);
        supervisor.processRequest(request2);
        supervisor.processRequest(request3);
    }
}

golang实现

package main

import "fmt"

type LeaveRequest struct {
	employee string
	days     int
}

func NewLeaveRequest(employee string, days int) *LeaveRequest {
	return &LeaveRequest{
		employee: employee,
		days:     days,
	}
}

type Approver interface {
	processRequest(request LeaveRequest)
}

type Supervisor struct {
	nextApprover Approver
}

func (s *Supervisor) processRequest(request LeaveRequest) {
	if request.days <= 2 {
		fmt.Printf("主管批准的员工休假申请:%d\n", request.days)
	} else if s.nextApprover != nil {
		s.nextApprover.processRequest(request)
	} else {
		fmt.Printf("主管未批准的员工休假申请:%d\n", request.days)
	}
}

type DepartmentManager struct {
	nextApprover Approver
}

func (s *DepartmentManager) processRequest(request LeaveRequest) {
	if request.days <= 5 {
		fmt.Printf("部门经理批准的员工休假申请:%d\n", request.days)
	} else if s.nextApprover != nil {
		s.nextApprover.processRequest(request)
	} else {
		fmt.Printf("部门经理未批准的员工休假申请:%d\n", request.days)
	}
}

type GeneralManager struct {
	nextApprover Approver
}

func (s *GeneralManager) processRequest(request LeaveRequest) {
	if request.days > 5 {
		fmt.Printf("总经理经理批准的员工休假申请:%d\n", request.days)
	} else {
		fmt.Printf("总经理未批准的员工休假申请:%d\n", request.days)
	}
}

func main() {
	// 创建处理者对象
	supervisor := &Supervisor{}
	departmentManager := &DepartmentManager{}
	generalManager := &GeneralManager{}

	// 设置处理者之间的关系
	supervisor.nextApprover = departmentManager
	departmentManager.nextApprover = generalManager

	// 创建请假请求
	request1 := LeaveRequest{employee: "John", days: 1}
	request2 := LeaveRequest{employee: "Alice", days: 3}
	request3 := LeaveRequest{employee: "Bob", days: 7}

	supervisor.processRequest(request1)
	supervisor.processRequest(request2)
	supervisor.processRequest(request3)
}

6、访问者模式(Visitor

  • 目的:定义一种新的操作,而无需修改被操作的对象。通过在被访问的对象上添加一个接受访问者的方法,可以使对象在不改变自己的类结构的前提下,让外部类定义其操作。
  • 应用场景:当有一个稳定的数据结构,但是需要对该数据结构进行多种不同的操作时,可以使用访问者模式;当类的结构经常发生变化,但对类的操作相对稳定时,可以使用访问者模式。
  • 案例:一个图形库的例子,其中有不同类型的图形(如圆、矩形)和不同的操作(如绘制、移动)。使用访问者模式可以轻松地添加新的图形类型或操作,而不影响已有的类结构。
  • 结构图

img

Java实现

// Shape.java
// 抽象元素 - 图形
interface Shape {
    void accept(Visitor visitor);
}

// Circle.java
// 具体元素 - 圆
class Circle implements Shape {
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

// Rectangle.java
// 具体元素 - 矩形
class Rectangle implements Shape {
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

// Visitor.java
// 抽象访问者
interface Visitor {
    void visit(Circle circle);
    void visit(Rectangle rectangle);
}

// DrawVisitor.java
// 具体访问者 - 绘制操作
class DrawVisitor implements Visitor {
    @Override
    public void visit(Circle circle) {
        System.out.println("Drawing Circle");
    }

    @Override
    public void visit(Rectangle rectangle) {
        System.out.println("Drawing Rectangle");
    }
}

// MoveVisitor.java
// 具体访问者 - 移动操作
class MoveVisitor implements Visitor {
    @Override
    public void visit(Circle circle) {
        System.out.println("Moving Circle");
    }

    @Override
    public void visit(Rectangle rectangle) {
        System.out.println("Moving Rectangle");
    }
}

// Main.java
// 客户端
public class Main {
    public static void main(String[] args) {
        Shape circle = new Circle();
        Shape rectangle = new Rectangle();

        Visitor drawVisitor = new DrawVisitor();
        Visitor moveVisitor = new MoveVisitor();

        // 绘制操作
        System.out.println("== 绘制操作 ==");
        circle.accept(drawVisitor);
        rectangle.accept(drawVisitor);
        // 移动操作
        System.out.println("== 移动操作 ==");
        circle.accept(moveVisitor);
        rectangle.accept(moveVisitor);
    }
}

golang实现

package main

import "fmt"

type Shape interface {
    accept(Visitor)
}

type Circle struct {
}

func (c *Circle) accept(visitor Visitor) {
    visitor.visitCircle(c)
}

type Rectangle struct {
}

func (r *Rectangle) accept(visitor Visitor) {
    visitor.visitRectangle(r)
}

type Visitor interface {
    visitCircle(*Circle)
    visitRectangle(*Rectangle)
}

type DrawVisitor struct{}

func (d *DrawVisitor) visitCircle(c *Circle) {
    fmt.Println(" 绘制圆形 ")
}

func (d *DrawVisitor) visitRectangle(c *Rectangle) {
    fmt.Println(" 绘制矩形 ")
}

type MoveVisitor struct{}

func (m *MoveVisitor) visitCircle(c *Circle) {
    fmt.Println(" 移动圆形 ")
}

func (m *MoveVisitor) visitRectangle(c *Rectangle) {
    fmt.Println(" 移动矩形 ")
}

func main() {
    circle := &Circle{}
    rectangle := &Rectangle{}

    drawVisitor := &DrawVisitor{}
    moveVisitor := &MoveVisitor{}

    // 绘制操作
    fmt.Println("== 绘制操作 ==")
    circle.accept(drawVisitor)
    rectangle.accept(drawVisitor)

    // 移动操作
    fmt.Println("== 移动操作 ==")
    circle.accept(moveVisitor)
    rectangle.accept(moveVisitor)

}

7、模板方法模式(Template Method)

  • 目的:定义一个算法的骨架,将其中的某些步骤延迟到子类中实现。通过这种方式,模板方法模式使得算法的结构不变,但可以灵活地扩展和修改其中的某些步骤,而不影响整体算法的结构。
  • 应用场景:当一个算法的整体结构已经确定,但其中的某些步骤可能由于应用的不同而变化时;多个类中存在相似的算法流程,可以将这些流程提取到一个公共的父类中,减少代码重复,提高代码的可维护性;在框架设计中,模板方法模式经常被用于定义框架的基本流程,而将一些具体实现留给子类来完成。
  • 案例:一个炒菜的例子,炒菜的步骤包括加热油、放入食材、翻炒等。这些步骤的顺序在不同的炒菜中可能有所不同。模板方法模式可以定义一个炒菜的模板,具体的炒菜类只需实现其中的具体步骤。

Java实现

// CookingTemplate.java
// 抽象类 - 炒菜模板
abstract class CookingTemplate {
    // 模板方法
    public final void cook() {
        heatOil();
        addIngredients();
        stirFry();
        serve();
    }

    // 具体步骤1 - 加热油
    protected void heatOil() {
        System.out.println("热油");
    }

    // 具体步骤2 - 放入食材
    protected abstract void addIngredients();

    // 具体步骤3 - 翻炒
    protected void stirFry() {
        System.out.println("翻炒");
    }

    // 具体步骤4 - 上菜
    protected void serve() {
        System.out.println("上菜");
    }
}

// GreenPepperBeefCooking.java
// 具体类 - 青椒炒肉
class GreenPepperBeefCooking extends CookingTemplate {
    @Override
    protected void addIngredients() {
        System.out.println("放入青椒和牛肉");
    }
}

// KungPaoChickenCooking.java
// 具体类 - 宫保鸡丁
class KungPaoChickenCooking extends CookingTemplate {
    @Override
    protected void addIngredients() {
        System.out.println("放入鸡肉、花生和辣椒");
    }
}

// Main.java
// 客户端
public class Main {
    public static void main(String[] args) {
        CookingTemplate greenPepperBeef = new GreenPepperBeefCooking();
        CookingTemplate kungPaoChicken = new KungPaoChickenCooking();

        // 使用模板方法炒青椒肉
        greenPepperBeef.cook();

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

        // 使用模板方法炒宫保鸡丁
        kungPaoChicken.cook();
    }
}

golang实现

package main

import "fmt"

// CookingProcess 定义炒菜的接口
type CookingProcess interface {
	HeatOil()
	AddMainIngredients()
	StirFry()
	Serve()
}

// CookingTemplate 提供了一个模板方法
type CookingTemplate struct {
	process CookingProcess
}

func (c *CookingTemplate) Cook() {
	c.process.HeatOil()
	c.process.AddMainIngredients()
	c.process.StirFry()
	c.process.Serve()
}

// GreenPepperBeef 实现 CookingProcess 接口
type GreenPepperBeef struct{}

func (g *GreenPepperBeef) HeatOil() {
	fmt.Println("热油")
}

func (g *GreenPepperBeef) AddMainIngredients() {
	fmt.Println("放入青椒和牛肉")
}

func (g *GreenPepperBeef) StirFry() {
	fmt.Println("翻炒")
}

func (g *GreenPepperBeef) Serve() {
	fmt.Println("上菜")
}

// KungPaoChicken 实现 CookingProcess 接口
type KungPaoChicken struct{}

func (k *KungPaoChicken) HeatOil() {
	fmt.Println("热油")
}

func (k *KungPaoChicken) AddMainIngredients() {
	fmt.Println("放入鸡肉、花生和辣椒")
}

func (k *KungPaoChicken) StirFry() {
	fmt.Println("翻炒")
}

func (k *KungPaoChicken) Serve() {
	fmt.Println("上菜")
}

func main() {
	greenPepperBeef := &GreenPepperBeef{}
	kungPaoChicken := &KungPaoChicken{}

	greenPepperBeefTemplate := CookingTemplate{greenPepperBeef}
	kungPaoChickenTemplate := CookingTemplate{kungPaoChicken}

	// 使用模板方法炒青椒肉
	greenPepperBeefTemplate.Cook()

	fmt.Println("------------------")

	// 使用模板方法炒宫保鸡丁
	kungPaoChickenTemplate.Cook()
}

8、中介者模式(Mediator

  • 目的:减少组件之间的直接通信,而是通过一个中介者对象进行通信。通过引入中介者,组件之间不需要直接知道彼此,而是通过中介者进行协调和通信,从而降低了组件之间的耦合度。
  • 应用场景:中介者模式有助于实现组件之间的松散耦合,使得系统更易于扩展和维护。
  • 案例:一个聊天室的例,在聊天室中,多个用户之间需要相互通信,但不希望每个用户都直接与其他用户通信。通过引入中介者,用户可以通过中介者进行消息的发布和接收,而不需要直接知道其他用户的存在。
  • 结构图

img

Java实现

// ChatMediator.java
// 中介者接口
interface ChatMediator {
    void sendMessage(String message, User user);

    void addUser(User user);
}

// ChatMediatorImpl.java
// 具体中介者
class ChatMediatorImpl implements ChatMediator {
    private List<User> users;

    public ChatMediatorImpl() {
        this.users = new ArrayList<>();
    }

    @Override
    public void sendMessage(String message, User user) {
        for (User item : users) {
            // 发送消息给其他用户(排除发送者本身)
            if (item != user) {
                item.receiveMessage(message);
            }
        }
    }

    @Override
    public void addUser(User user) {
        users.add(user);
    }
}

// User.java
// 抽象用户类
abstract class User {
    protected ChatMediator mediator;
    protected String name;

    public User(ChatMediator mediator, String name) {
        this.mediator = mediator;
        this.name = name;
    }

    public abstract void sendMessage(String message);

    public abstract void receiveMessage(String message);
}

// User.java
// 具体用户类
class ChatUser extends User {
    public ChatUser(ChatMediator mediator, String name) {
        super(mediator, name);
    }

    @Override
    public void sendMessage(String message) {
        System.out.println(name + " 发送消息: " + message);
        mediator.sendMessage(message, this);
    }

    @Override
    public void receiveMessage(String message) {
        System.out.println(name + " 收到消息: " + message);
    }
}

public class Main {
    public static void main(String[] args) {
        ChatMediator mediator = new ChatMediatorImpl();

        User user1 = new ChatUser(mediator, "User1");
        User user2 = new ChatUser(mediator, "User2");
        User user3 = new ChatUser(mediator, "User3");

        mediator.addUser(user1);
        mediator.addUser(user2);
        mediator.addUser(user3);

        user1.sendMessage("Hello, everyone!");
    }
}

golang实现

package main

import "fmt"

// 中介者接口
type ChatMediator interface {
    SendMessage(message string, user *User)
}

// 具体中介者
type ChatMediatorImpl struct {
    users []*User
}

func NewChatMediator() *ChatMediatorImpl {
    return &ChatMediatorImpl{users: make([]*User, 0)}
}

func (c *ChatMediatorImpl) AddUser(user *User) {
    c.users = append(c.users, user)
}

func (c *ChatMediatorImpl) SendMessage(message string, user *User) {
    for _, u := range c.users {
        if u != user {
            u.ReceiveMessage(message)
        }
    }
}

// 用户结构体
type User struct {
    mediator ChatMediator
    name     string
}

func NewUser(mediator ChatMediator, name string) *User {
    return &User{mediator: mediator, name: name}
}

func (u *User) SendMessage(message string) {
    fmt.Printf("%s 发送消息: %s\n", u.name, message)
    u.mediator.SendMessage(message, u)
}

func (u *User) ReceiveMessage(message string) {
    fmt.Printf("%s 收到消息: %s\n", u.name, message)
}

func main() {
    mediator := NewChatMediator()

    user1 := NewUser(mediator, "User1")
    user2 := NewUser(mediator, "User2")
    user3 := NewUser(mediator, "User3")

    mediator.AddUser(user1)
    mediator.AddUser(user2)
    mediator.AddUser(user3)

    user1.SendMessage("Hello, everyone!")
}

9、备忘录模式(Memento

  • 目的:在不破坏封装的前提下,捕获一个对象的内部状态,以便后续恢复对象到这个状态。这种模式通常用于需要提供撤销(Undo)操作的场景,或者需要在某个时刻记录对象的状态,以便之后进行还原。
  • 应用场景:在数据库或事务管理系统中,备忘录模式可以用于记录事务的状态,以便在发生错误时回滚到先前的状态;在游戏中,备忘录模式可以用于保存玩家的游戏进度,以便在需要时恢复到之前的状态。
  • 案例:一个文本编辑器的例子,用户可以输入文本并执行撤销操作。备忘录模式可以用于保存文本编辑器的历史状态,以便用户可以撤销到先前的编辑状态。

Java实现

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

// Memento.java
// 备忘录类
class Memento {
    private final String state;

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

    String getState() {
        return state;
    }
}

// TextEditor.java
// 原发器类
class TextEditor {
    private String content;

    void setContent(String content) {
        this.content = content;
    }

    String getContent() {
        return content;
    }

    Memento save() {
        return new Memento(content);
    }

    void undoToLastSave(Object obj) {
        if (obj instanceof Memento) {
            Memento memento = (Memento) obj;
            content = memento.getState();
        }
    }
}

// Caretaker.java
// 负责人类
class Caretaker {
    private final List<Memento> savedStates = new ArrayList<>();

    void addMemento(Memento m) {
        savedStates.add(m);
    }

    Memento getMemento(int index) {
        return savedStates.get(index);
    }
}

// Main.java
public class Main {
    public static void main(String[] args) {
        TextEditor editor = new TextEditor();
        Caretaker caretaker = new Caretaker();

        editor.setContent("State #1");
        editor.setContent("State #2");
        caretaker.addMemento(editor.save());

        editor.setContent("State #3");
        caretaker.addMemento(editor.save());

        editor.setContent("State #4");

        editor.undoToLastSave(caretaker.getMemento(1));
        System.out.println("当前内容: " + editor.getContent());

        editor.undoToLastSave(caretaker.getMemento(0));
        System.out.println("当前内容: " + editor.getContent());
    }
}

golang实现

package main

import "fmt"

// 备忘录类
type Memento struct {
	state string
}

// 原发器类
type TextEditor struct {
	content string
}

func (t *TextEditor) SetContent(content string) {
	t.content = content
}

func (t *TextEditor) GetContent() string {
	return t.content
}

func (t *TextEditor) Save() *Memento {
	return &Memento{state: t.content}
}

func (t *TextEditor) UndoToLastSave(m *Memento) {
	t.content = m.state
}

// 负责人类
type Caretaker struct {
	mementos []*Memento
}

func (c *Caretaker) AddMemento(m *Memento) {
	c.mementos = append(c.mementos, m)
}

func (c *Caretaker) GetMemento(index int) *Memento {
	return c.mementos[index]
}

func main() {
	editor := &TextEditor{}
	caretaker := &Caretaker{}

	editor.SetContent("State #1")
	editor.SetContent("State #2")
	caretaker.AddMemento(editor.Save())

	editor.SetContent("State #3")
	caretaker.AddMemento(editor.Save())

	editor.SetContent("State #4")

	editor.UndoToLastSave(caretaker.GetMemento(1))
	fmt.Println("当前内容:", editor.GetContent())

	editor.UndoToLastSave(caretaker.GetMemento(0))
	fmt.Println("当前内容:", editor.GetContent())
}

10、解释器模式(Interpreter

  • 目的:定义一种语言的文法,并在这个语言中解释句子的意义。
  • 应用场景:解决一些特定类型的问题,例如编译器、正则表达式解析、自然语言处理等。
  • 案例:用解释器模式实现一个简单的布尔逻辑解释器,解释器可以解析和计算像 true AND falsetrue OR (false AND true) 这样的布尔表达式。
  • 结构图:

img

Java实现

// Expression.java
// 抽象表达式接口
interface Expression {
    boolean interpret(Context context);
}

// VariableExpression.java
// 终结符表达式
class VariableExpression implements Expression {
    private String name;

    public VariableExpression(String name) {
        this.name = name;
    }

    @Override
    public boolean interpret(Context context) {
        return context.lookup(name);
    }
}

// AndExpression.java
// 非终结符表达式 - AND
class AndExpression implements Expression {
    private Expression expr1;
    private Expression expr2;

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

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

// OrExpression.java
// 非终结符表达式 - OR
class OrExpression implements Expression {
    private Expression expr1;
    private Expression expr2;

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

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

// Context.java
// 上下文类,用于变量赋值
class Context {
    private Map<String, Boolean> variables = new HashMap<>();

    public void assign(String var, boolean value) {
        variables.put(var, value);
    }

    public boolean lookup(String var) {
        return variables.getOrDefault(var, false);
    }
}

// Main.java
// 客户端使用
public class Main {
    public static void main(String[] args) {
        // 构建布尔表达式 (true AND false) OR (false AND true)
        Expression expr = new OrExpression(
                new AndExpression(new VariableExpression("X"), new VariableExpression("Y")),
                new AndExpression(new VariableExpression("A"), new VariableExpression("B"))
        );

        Context context = new Context();
        context.assign("X", true);
        context.assign("Y", false);
        context.assign("A", false);
        context.assign("B", true);

        boolean result = expr.interpret(context);

        System.out.println("Result: " + result);
    }
}

golang实现

package main

import "fmt"

type Expression interface {
    interpret(Context) bool
}

type VariableExpression struct {
    name string
}

func (v *VariableExpression) interpret(context Context) bool {
    return context.lookup(v.name)
}

type AndExpression struct {
    expr1 Expression
    expr2 Expression
}

func (a *AndExpression) interpret(context Context) bool {
    return a.expr1.interpret(context) && a.expr2.interpret(context)
}

type OrExpression struct {
    expr1 Expression
    expr2 Expression
}

func (a *OrExpression) interpret(context Context) bool {
    return a.expr1.interpret(context) || a.expr2.interpret(context)
}

type Context struct {
    variables map[string]bool
}

func NewContext() *Context {
    return &Context{
        variables: make(map[string]bool, 8),
    }
}

func (c *Context) assign(key string, value bool) {
    c.variables[key] = value
}

func (c *Context) lookup(key string) bool {
    return c.variables[key]
}

func main() {
    // 构建布尔表达式 (true AND false) OR (true AND true)
    expr := &OrExpression{
        expr1: &AndExpression{expr1: &VariableExpression{name: "X"}, expr2: &VariableExpression{name: "Y"}},
        expr2: &AndExpression{expr1: &VariableExpression{name: "A"}, expr2: &VariableExpression{name: "B"}},
    }

    context := NewContext()

    context.assign("X", true)
    context.assign("Y", false)
    context.assign("A", true)
    context.assign("B", true)

    res := expr.interpret(*context)
    fmt.Printf("result : %v", res)
}

11、迭代器模式(Iterator

  • 目的:提供一种访问集合元素的统一接口,而不暴露底层集合的实现细节。它属于行为型模式,通过定义一个迭代器接口,客户端可以遍历集合而不必关心底层数据结构。
  • 应用场景:集合类的遍历,不同集合类型的统一访问。
  • 案例:一个图书馆的书籍管理系统,其中包含不同类型的书籍,例如小说、科普书、艺术书等。使用迭代器模式可以实现一个统一的接口,用于遍历图书馆中的不同类型的书籍。

Java实现

// Book.java
// 书籍类
class Book {
    private String title;

    public Book(String title) {
        this.title = title;
    }

    public String getTitle() {
        return title;
    }
}

// Library.java
// 书籍集合类
class Library implements Iterable<Book> {
    private List<Book> books;

    public Library() {
        this.books = new ArrayList<>();
    }

    public void addBook(Book book) {
        books.add(book);
    }

    @Override
    public Iterator<Book> iterator() {
        return new BookIterator();
    }

    // 内部迭代器类
    private class BookIterator implements Iterator<Book> {
        private int index = 0;

        @Override
        public boolean hasNext() {
            return index < books.size();
        }

        @Override
        public Book next() {
            return books.get(index++);
        }
    }
}

// Main.java
// 客户端使用
public class Main {
    public static void main(String[] args) {
        Library library = new Library();
        library.addBook(new Book("Java Programming"));
        library.addBook(new Book("Design Patterns"));
        library.addBook(new Book("Artificial Intelligence"));

        // 使用迭代器遍历书籍集合
        Iterator<Book> iterator = library.iterator();
        while (iterator.hasNext()) {
            Book book = iterator.next();
            System.out.println("Book Title: " + book.getTitle());
        }
    }
}

golang实现

package main

import (
    "fmt"
)

// Book 结构表示书籍
type Book struct {
    title string
}

// Library 结构表示图书馆
type Library struct {
    books []Book
}

// Iterator 接口表示迭代器
type Iterator interface {
    HasNext() bool
    Next() Book
}

// BookIterator 结构实现 Iterator 接口
type BookIterator struct {
    library *Library
    index   int
}

func (bi *BookIterator) HasNext() bool {
    return bi.index < len(bi.library.books)
}

func (bi *BookIterator) Next() Book {
    book := bi.library.books[bi.index]
    bi.index++
    return book
}

// NewBookIterator 返回一个 BookIterator 实例
func NewBookIterator(library *Library) Iterator {
    return &BookIterator{library: library, index: 0}
}

// NewLibrary 返回一个 Library 实例
func NewLibrary() *Library {
    return &Library{books: make([]Book, 0)}
}

// AddBook 向图书馆中添加书籍
func (l *Library) AddBook(book Book) {
    l.books = append(l.books, book)
}

func main() {
    library := NewLibrary()
    library.AddBook(Book{"Java Programming"})
    library.AddBook(Book{"Design Patterns"})
    library.AddBook(Book{"Artificial Intelligence"})

    // 使用迭代器遍历书籍集合
    iterator := NewBookIterator(library)
    for iterator.HasNext() {
        book := iterator.Next()
        fmt.Println("Book Title:", book.title)
    }
}
  • 14
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值