unity中接口的作用及示例

今天写类胡闹厨房的游戏适当的用接口真的很舒服,在像胡闹厨房这样的游戏开发里面把Counters谨慎的继承在一个BaseCounter里面然后在BaseCounter写所有物品接口函数真的很清爽代码。。

using UnityEngine;

public class BaseCounter : MonoBehaviour, IKitchenObjectParent
{
    [SerializeField] private Transform counterTopPoint; // 放置物品的位置

    private KitchenObject kitchenObject; // 物品的实例
    
    //E键,方便让继承他的类复写用virtual
    public virtual void Interact(Player player)
    {
        Debug.Log("BaseCounter.Interact();");
    }

    //F键,方便让继承他的类复写用virtual
    public virtual void InteractAlternate(Player player)
    {
        Debug.Log("BaseCounter.InteractAlternate();");
    }

    #region 物品接口类函数

    // 获取物品的跟随点位置(用于设置物品位置)

    public Transform GetKitchenObjectFollowTransform()
    {
        return counterTopPoint;
    }

    public void SetKitchenObject(KitchenObject kitchenObject)
    {
        this.kitchenObject = kitchenObject; // 记录物品的实例
    }

    // 获取当前物品

    public KitchenObject GetKitchenObject()
    {
        return kitchenObject;
    }

    // 清空当前物品

    public void ClearKitchenObject()
    {
        kitchenObject = null;
    }

    // 是否有物品

    public bool HasKitchenObject()
    {
        return kitchenObject is not null;
    }

    #endregion

    
}

1. 定义行为的契约

接口是一个契约,它规定了实现该接口的类需要提供哪些方法和事件。这样,接口的使用者无需关心具体的实现细节,只需要依赖接口定义的方法和事件。这提供了高度的抽象性

举个例子:

假设你有一个 IProgress 接口,定义了一个 OnProgressChanged 事件。这意味着任何实现 IProgress 接口的类都可以使用这个事件。

public interface IProgress
{
    event EventHandler<ProgressChangedEventArgs> OnProgressChanged;
}

任何实现这个接口的类(比如 CookingProcessLoadingProcess)都应该提供进度变化的事件通知,而调用者只关心接口定义,甚至不关心具体是哪个类在使用这个接口。

2. 统一的事件处理机制

接口使得不同类型的对象可以通过统一的方式进行事件处理。你可以用相同的方式订阅和处理不同类实例的事件,即使它们在逻辑上有很大差异。

举个例子:

有多个类实现了 IProgress 接口,比如 CookingProcessLoadingProcess。它们都触发 OnProgressChanged 事件,UI 或其他代码可以统一使用 IProgress 来订阅和处理这些事件,而无需关心具体是哪个类。

public void SubscribeToProgress(IProgress progress)
{
    progress.OnProgressChanged += (sender, args) =>
    {
        // 处理进度更新,更新进度条
    };
}

(注,我用了lambda表达式,这样我认为代码少一点看起来清爽一点)

这样,不管传递的是 CookingProcess 还是 LoadingProcess,你都可以使用相同的事件处理方法。

3. 解耦合

接口帮助解耦业务逻辑和事件的发布者/订阅者。通过接口,类与类之间的依赖变得更加松散。例如,UI类可以订阅 IProgress 接口的事件,而无需知道到底是哪个具体的类在触发事件。反过来,触发事件的类也不需要知道谁订阅了这些事件。

public class CookingProcess : IProgress
{
    public event EventHandler<ProgressChangedEventArgs> OnProgressChanged;
    
    public void UpdateProgress(float progress)
    {
        OnProgressChanged?.Invoke(this, new ProgressChangedEventArgs { ProgressNormalized = progress });
    }
}

在上面的代码中,CookingProcess 只关心如何更新进度,而不需要知道谁在订阅它的进度事件。这样可以有效减少类之间的耦合。

4. 多态性和扩展性

接口允许以更灵活的方式扩展和替换实现类。如果希望换掉某个实现 IProgress 接口的类,只需要保证新的类实现了 IProgress 接口,而不需要修改其他使用该接口的代码。

例如,假设先使用了 CookingProcess 类,它触发了进度更新事件。如果想用一个新的类 LoadingProcess 替换它,只需要确保 LoadingProcess 也实现了 IProgress 接口。

 
public class LoadingProcess : IProgress
{
    public event EventHandler<ProgressChangedEventArgs> OnProgressChanged;
    
    public void UpdateProgress(float progress)
    {
        OnProgressChanged?.Invoke(this, new ProgressChangedEventArgs { ProgressNormalized = progress });
    }
}

5. 支持不同对象使用同一个事件

正如我所提到的,接口让不同代码使用同一个事件。不同的类可以实现相同的事件接口,订阅方不需要知道具体的类类型,只需要关心接口定义。这使得系统可以灵活地组合和替换不同的组件。

小结

接口提供了:

  • 统一的行为规范,让不同类遵循相同的协议;
  • 解耦,通过接口订阅/发布事件,不需要直接依赖具体的类;
  • 多态性和扩展性,通过实现接口,可以轻松替换不同的实现,而不需要修改其他代码;
  • 事件处理的统一机制,让多个不同类的事件可以以相同的方式进行处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值