[UE5 设计模式] 桥接模式Bridge Pattern


参考材料
1. 【UE4 设计模式】策略模式 Strategy Pattern
2. 桥接模式
3. 游戏开发设计模式之桥接模式

1. 概述

1.1 描述

$\cdot$ 桥接(Bridge) 是用于把抽象化与实现化解耦, 使得二者可以独立变化. 这种类型的设计模式属于结构型模式, 它通过提供抽象化和实现化之间的桥接结构, 来实现二者的解耦.
$\\$ 这种模式涉及到一个作为桥接的接口, 使得实体类的功能独立于接口实现类, 这两种类型的类可被结构化改变而互不影响.
$\\$ 桥接模式的目的是将抽象与实现分离, 使它们可以独立地变化, 该模式通过将一个对象的抽象部分与它的实现部分分离, 使它们可以独立地改变. 它通过组合的方式, 而不是继承的方式, 将抽象和实现的部分连接起来.

1.2 套路

$\cdot$ 实现方式:
$\\$ 1) 分离多角度分类: 将不同角度的分类逻辑分离, 允许它们独立变化.
$\\$ 2) 减少耦合: 降低抽象与实现之间的耦合度.

$\cdot$ 关键代码:
$\\$ 1) 抽象类: 定义一个抽象类, 作为系统的一部分.
$\\$ 2) 实现类: 定义一个或多个实现类, 与抽象类通过聚合(而非继承) 关联.

$\cdot$ 结构:
$\\$ 以下是桥接模式的几个关键角色:
$\\$ 1) 抽象(Abstraction): 定义抽象接口, 通常包含对实现接口的引用.
$\\$ 2) 扩展抽象(Refined Abstraction): 对抽象的扩展, 可以是抽象类的子类或具体实现类.
$\\$ 3) 实现(Implementor): 定义实现接口, 提供基本操作的接口.
$\\$ 4) 具体实现(Concrete Implementor): 实现实现接口的具体类.

1.3 使用场景

$\cdot$ 当系统可能从多个角度进行分类, 且每个角度都可能独立变化时, 桥接模式是合适的.

1.4 优缺点

$\cdot$ 优点:
$\\$ 1) 抽象与实现分离: 提高了系统的灵活性和可维护性.
$\\$ 2) 扩展能力强: 可以独立地扩展抽象和实现.
$\\$ 3) 实现细节透明: 用户不需要了解实现细节.

$\cdot$ 缺点:
$\\$ 1) 理解与设计难度: 桥接模式增加了系统的理解与设计难度.
$\\$ 2) 聚合关联: 要求开发者在抽象层进行设计与编程.

2. UE5实践

我们有一个作为桥接实现的DrawAPI接口和实现了DrawAPI接口的实体类RedCircle, GreenCircle. Shape是一个抽象类, 将使用DrawAPI的对象. BridgePatternDemo类使用Shape类来画出不同颜色的圆.

2.1 步骤1

创建桥接实现接口.


#pragma once


class FDrawAPI
{
public:
	void DrawCircle(int32 Radius, int32 X, int32 Y)
	{
	}
};

2.2 步骤2

创建实现了FDrawAPI接口的实体桥接实现类.


#pragma once

#include "DrawAPI.h"
#include "CoreMinimal.h"


class FRedCircle final : public FDrawAPI
{
public:
	virtual void DrawCircle(int32 Radius, int32 X, int32 Y)
	{
		UE_LOG(LogTemp, Log, TEXT("Drawing Circle[ color: red, radius: %d, x: %d, %d]"), Radius, X, Y);
	}
};


#pragma once

#include "DrawAPI.h"
#include "CoreMinimal.h"


class FGreenCircle final : public FDrawAPI
{
public:
	virtual void DrawCircle(int32 Radius, int32 X, int32 Y)
	{
		UE_LOG(LogTemp, Log, TEXT("Drawing Circle[ color: green, radius: %d, x: %d, %d]"), Radius, X, Y);
	}
};

2.3 步骤3

使用FDrawAPI接口创建抽象类Shape.


#pragma once

#include "DrawAPI.h"
#include "CoreMinimal.h"


class FShape
{
public:
	virtual void Draw() = 0;

protected:
	FShape(FDrawAPI& InDrawAPI) : DrawAPI(MoveTemp(InDrawAPI))
	{
	}

protected:
	FDrawAPI DrawAPI;
};

2.4 步骤4

创建实现了Shape抽象类的实体类.


#pragma once

#include "Shape.h"


class FCircle final : public FShape
{
public:
	FCircle(int32 InX, int32 InY, int32 InRadius, FDrawAPI& DrawAPI) : Super(DrawAPI), X(InX), Y(InY), Radius(InRadius)
	{
	}

	void Draw()
	{
		DrawAPI.DrawCircle(Radius, X, Y);
	}

private:
	int32 X;

	int32 Y;

	int32 Radius;
};

2.5 步骤5

使用FShape和FDrawAPI类画出不同颜色的圆.


#include "RedCircle.h"
#include "GreenCircle.h"
#include "Circle.h"


int main(int argc, char* argv[]) 
{
	FShape* RedCircleShape = new FCircle(100, 100, 10, RedCircle());
	FShape* GreenCircleShape = new FCircle(100, 100, 10, GreenCircle());

	RedCircleShape->Draw();
	GreenCircleShape->Draw();

	delete RedCircleShape;
	RedCircleShape = nullptr;

	delete GreenCircleShape;
	GreenCircleShape = nullptr;

	return 0;
}

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注