Unity桥接模式

在游戏开发中,经常会遇到这样的问题:

当系统中存在多个可独立变化的维度时,如果直接通过继承进行组合,随着功能扩展,类数量往往会迅速膨胀,代码也会变得难以维护。以武器系统为例,武器类型和攻击方式本质上是两个独立变化的方向,如果将二者强行绑定在一起,后期无论新增武器还是新增伤害类型,都会带来大量重复修改。

桥接模式正是为了解决这一类问题而出现的。它通过将抽象与实现解耦,使不同维度可以独立扩展,从而避免继承结构失控。下面我将结合 Unity 中一个简单的武器与攻击方式示例,说明桥接模式在实际项目中的应用思路。

1.创建攻击类型接口

这个接口主要定义了一个攻击类型的接口,实现了两种攻击方式,普通攻击和元素攻击。

cs 复制代码
using UnityEngine;

public interface IAttackType
{
    void Attack();
}

public class NormalAttack : IAttackType
{
    public void Attack()
    {
        Debug.Log("普通攻击");
    }
}

public class ElementAttack : IAttackType
{
    public void Attack()
    {
        Debug.Log("元素攻击");
    }
}

2.创建武器抽象类(抽象层)

这个接口起到了桥的作用,将武器和攻击类型连接了起来,只需要编写一次就能实现之后添加各种类型的伤害,比如现在是普通和元素,之后添加蒸发融化都可以,而且不需要改动原本的代码。

为什么 Weapon 是"桥"

Weapon 本身并不关心具体的攻击实现,它只负责维护对攻击类型接口的引用,并在合适的时机调用。武器和攻击方式因此可以独立扩展,二者之间通过 Weapon 这一抽象层进行桥接。

cs 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//武器接口,链接武器和攻击类型的桥梁
public abstract class Weapon
{
    protected IAttackType attackType;
    //构造函数获取攻击类型
    protected Weapon(IAttackType attackType)
    {
        this.attackType = attackType;
    }

    public abstract void Use();
}
//刀剑类武器
public class Sword : Weapon
{
    //使用基类构造函数
    public Sword(IAttackType attackType) : base(attackType) { }

    public override void Use()
    {
        Debug.Log("挥动剑:");
        attackType.Attack();//调用攻击类型Attack()方法
    }
}
//弓箭类武器
public class Bow : Weapon
{
    //使用基类构造函数
    public Bow(IAttackType attackType) : base(attackType) { }

    public override void Use()
    {
        Debug.Log("射箭:");
        attackType.Attack();//调用攻击类型Attack()方法
    }
}

3.使用

当你要使用某种类型的武器和伤害的时候直接在New武器的时候把伤害类型传进去即可。

cs 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour
{
    void Start()
    {
        Weapon sword1 = new Sword(new ElementAttack());//武器元素攻击
        Weapon sword2 = new Sword(new NormalAttack());// 武器普通攻击
        Weapon bow1 = new Bow(new NormalAttack());// 普通伤害弓箭
        Weapon bow2 = new Bow(new  ElementAttack());//  元素伤害弓箭

        sword1.Use();
        sword2.Use();
        bow1.Use();
        bow2.Use();
    }
}

4.运行效果

将玩家脚本加到场景中的空对象上,可以看到各个类型的武器和伤害都打印了出来。

5.总结

通过这个示例可以看出,桥接模式的核心价值并不在于代码本身有多复杂,而在于它对系统结构的约束方式。通过在抽象层中持有实现层的接口引用,武器类型和攻击方式这两个变化维度得以解耦,它们可以在互不影响的情况下独立扩展。当后续需要新增攻击类型(例如元素反应、特殊结算规则等)时,只需扩展攻击实现即可,无需修改已有的武器代码。

在实际项目中,这种设计方式尤其适合用于武器系统、技能系统、AI 行为、平台适配等存在多维度变化的场景。合理地使用桥接模式,可以让系统在功能不断演进的过程中,避免因继承层级过深而失控。

相关推荐
winfreedoms1 小时前
VMware 桥接模式无法联网:从 DHCPDISCOVER 到静态 IP 的完整排障实战
网络协议·tcp/ip·ubuntu·桥接模式·vmware·嵌入式学习
淡海水4 小时前
01-05-运行时-JIT优化全景-内联去虚拟化边界检查消除
windows·c#·虚拟化·jit·内联·边界检查消除
波波00712 小时前
C# 15 重磅新特性: 带标签 break 与 continue:重新定义嵌套循环控制流
服务器·前端·c#
wujian831115 小时前
怎么用千问生成word文档:从「格式崩」到「一键过」,AI导出鸭打通最后半厘米
人工智能·ai·c#·word·豆包·deepseek·ai导出鸭
zlinear数据采集卡16 小时前
D223上位机C#开发实战:从帧解析到波形显示的完整实现
开发语言·arm开发·嵌入式硬件·fpga开发·开源·c#
唐青枫18 小时前
别把 ImmutableArray 当成只读 List:C#.NET 不可变数组深入详解
c#·.net
_ZHOURUI_H_20 小时前
Unity TCP底层极限拆解:粘包、半包、CRC、序列号、双缓冲到底怎么一起工作的?
网络·网络协议·tcp/ip·游戏·unity·游戏引擎·游戏开发
zlinear数据采集卡20 小时前
D223 ADC数据处理流水线:从原始采样值到工程单位的完整转换链
开发语言·arm开发·嵌入式硬件·fpga开发·开源·c#
workflower1 天前
例二:某汽车制造企业深度融合AI智能体,构建园区网络的智能运维体系
人工智能·机器学习·设计模式·机器人·云计算·汽车·制造