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

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

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

行为型模式(Behavioral Patterns)

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

1、观察者模式(Observer)

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

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 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)

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

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)操作时,可以使用命令模式。每个命令对象可以存储执行前的状态,以便在需要时撤销操作。案例:一个简单的遥控器应用,遥控器可以控制多个设备(例如电视、音响)并支持撤销操作。每个设备的操作都被封装成命令对象,遥控器通过调用这些命令对象来实现控制。结构图:

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)

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

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)

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

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)

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

Java实现

// ChatMediator.java

// 中介者接口

interface ChatMediator {

void sendMessage(String message, User user);

void addUser(User user);

}

// ChatMediatorImpl.java

// 具体中介者

class ChatMediatorImpl implements ChatMediator {

private List 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 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 false 或 true OR (false AND true) 这样的布尔表达式。结构图:

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 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 {

private List books;

public Library() {

this.books = new ArrayList<>();

}

public void addBook(Book book) {

books.add(book);

}

@Override

public Iterator iterator() {

return new BookIterator();

}

// 内部迭代器类

private class BookIterator implements Iterator {

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 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)

}

}

相关链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: