【问题标题】:using C# interface to create a Manager class that implementing a singleton pattern, but the child manager class does not have a singleton pattern使用 C# 接口创建实现单例模式的管理器类,但子管理器类没有单例模式
【发布时间】:2021-10-18 09:47:01
【问题描述】:

我正在创建一个Manager 类,它使用 C# 接口实现单例模式。

我想出了一个结构,将单例模式应用于Manager 类,将其继承给我的孩子,并扩展功能。 但是,如果我尝试从其他类访问它,我只能访问Manager 类。

我觉得我需要修改代码或结构,我该怎么办?

ISingleton.cs

using System;
using System.Collections.Generic;
using UnityEngine;

public interface ISingleton<T> where T : class
{
    void SetSingleton(T _classType, GameObject _obj);
    T GetInstance();
}

Singleton.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public abstract class Singleton<T> : MonoBehaviour , ISingleton<T> where T: class
{
    public static T instance = default;
    public void SetSingleton(T _class, GameObject _obj)
    {
        if (instance is null) instance = _class;
        else if(instance.Equals(_class))
        {
            Debug.LogError("Unexpected Instancing Singleton Occuired! from " + gameObject.name);
            Destroy(_obj);
            return;
        }
        DontDestroyOnLoad(_obj);
    }
    public T GetInstance()
    {
        return instance;
    }
}

Manager.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Manager : Singleton<Manager>,IManager
{
    public int data;

    protected virtual void Awake()
    {
        Initialize();
    }

    public virtual void Initialize()
    {
        SetSingleton(this,this.gameObject);
    }
}

游戏管理器

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameManager : Manager
{
    public int HP,point;
    protected override void Awake()
    {
        Initialize();
    }
    public override void Initialize()
    {
        SetSingleton(this, this.gameObject);
    }

    private void StartGame() => print("GameStart");
    private void PauseGame() => print("Game Paused");
    private void QuitGame() => Application.Quit();
}

下面是我的代码的粗略结构。

【问题讨论】:

  • 你不能通过使用接口来真正强制单例模式,因为没有什么可以阻止某人添加一个构造函数来让他们创建一个新实例。此外,GetInstance 方法必须是 static,这意味着它不能构成接口的一部分。

标签: c# unity3d design-patterns interface singleton


【解决方案1】:

您的Manager 类派生自Singleton&lt;Manager&gt;,它提供了获取ManagerSingleton&lt;Manager&gt;.GetInstance() 实例的方法。您的 GameManager 现在继承自 ManagerSingleton&lt;Manager&gt;

正如您已经在GameManager.Initialize() 中所做的那样,您可以使用SetSingleton 设置经理单例,并且它接受GameManager 作为参数,因为它需要Manager,这是您的GameManager IST。

但是你的GameManager仍然只实现Singleton&lt;Manager&gt;,这意味着GetInstance()方法只能返回一个Manager,而不是一个GameManager,虽然你得到的经理实际上是你的GameManager。您现在可以将其转换为 GameManager 并且它会起作用,尽管这将是一个相当不干净的解决方案。

也就是说:我认为尝试通过接口强制执行单例模式并不是一个干净的解决方案,正如 cmets 已经指出的那样。如果您想使用单例管理器实例,我建议您研究依赖注入。对于 Unity,我强烈推荐 Zenject。如果您在花点时间习惯之前从未使用过 DI,但正确使用它会使您的代码更干净;我不想在我的项目中错过它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-10
    相关资源
    最近更新 更多