C# 在C中创建静态虚拟工厂方法的正确方法#

C# 在C中创建静态虚拟工厂方法的正确方法#,c#,oop,inheritance,unity3d,design-patterns,C#,Oop,Inheritance,Unity3d,Design Patterns,我正在Unity3D中实现特效类(在FixedUpdate循环处于活动状态时应用行为的持续时间) 我有一个基本的抽象效果类,它的行为是跟踪持续时间,在持续时间结束时删除自身,并在持续时间结束时调用受保护的抽象效果函数。在派生类中,我重写_doEffect以创建具有不同行为的效果 public abstract class Effect : MonoBehaviour { public virtual float kDuration { get { return 1.0f; }}

我正在Unity3D中实现特效类(在FixedUpdate循环处于活动状态时应用行为的持续时间)

我有一个基本的抽象效果类,它的行为是跟踪持续时间,在持续时间结束时删除自身,并在持续时间结束时调用受保护的抽象效果函数。在派生类中,我重写_doEffect以创建具有不同行为的效果

public abstract class Effect : MonoBehaviour
{
    public virtual float kDuration { get { return 1.0f; }}
    public static bool IsStackable { get { return false; }}
    private float _elapsed = 0.0f;

    protected virtual void Start()
    {
        _elapsed = kDuration;
    }

    protected virtual void FixedUpdate()
    {
        _elapsed -= Time.fixedDeltaTime;
        if(_elapsed <= 0) {
            Destroy(this);
        }

        _doEffect();
    }

    protected abstract void _doEffect();
}
然后在基础课上

public static virtual Effect CreateEffect(GameObject obj)
{
    //T is somehow magically the type of the class you called this function on
    if(!T.IsStackable()) {
        //delete all components of type T on obj
    }
    T effect = obj.AddComponent<T>();
    return effect;
}
公共静态虚拟效果CreateEffect(GameObject obj)
{
//T是你调用这个函数的类的类型
如果(!T.IsStackable()){
//删除obj上T型的所有部件
}
T effect=obj.AddComponent();
回报效应;
}
显然,这是不可能的,除非我用泛型和反射做一些奇怪的事情,这看起来有点极端,可能不是正确的方法

关键是我需要一个执行1)、2)、3)的静态函数,我想要共享执行1)和2)的代码,1)依赖于bool,这对于每个派生类都是不同的

对于这些desiderata,什么是合适的工作设计

对于这些desiderata,什么是合适的工作设计

Unity是基于组件的,当您想以普通C#应用程序的方式使用它时,它会使事情变得复杂

最简单的方法是使用合成。使
效果
类成为自己的非抽象类。只是从
monobhavior
继承的普通类。您可以使用
AddComponent
轻松创建它的新实例,并使用
GetComponent
获取它。此脚本也可以在计时器计数完成后直接销毁自身,而不会出现任何问题

DerivedEffect
类中创建一个全局变量,以保存所创建的
Effect
脚本的实例,该变量可以反复使用,直到它变为null,这意味着脚本被销毁。请注意,此处不涉及继承,而
DerivedEffect
脚本仅用作管理
效果的脚本示例

对于这些desiderata,什么是合适的工作设计

Unity是基于组件的,当您想以普通C#应用程序的方式使用它时,它会使事情变得复杂

最简单的方法是使用合成。使
效果
类成为自己的非抽象类。只是从
monobhavior
继承的普通类。您可以使用
AddComponent
轻松创建它的新实例,并使用
GetComponent
获取它。此脚本也可以在计时器计数完成后直接销毁自身,而不会出现任何问题


DerivedEffect
类中创建一个全局变量,以保存所创建的
Effect
脚本的实例,该变量可以反复使用,直到它变为null,这意味着脚本被销毁。请注意,此处不涉及继承,而
DerivedEffect
脚本仅用作管理
效果的脚本示例。

如何使用
IsStackable
接口标记可堆叠效果,然后
if(Effect is IsStackable){…}
?这是在检查对象是否是IStackable,对吗?由于DerivedEffect.CreateEffect(obj)是一个静态函数,因此它没有要检查的对象。好的,在这种情况下,因为我们正在创建一个对象,所以检查它似乎有点奇怪,因为所讨论的bool实际上是类的特性,而不是一个特定的对象。我们还可以想象这样的情况,可能基于类的一个特性,我们不想实例化效果,然后实例化效果只是为了检查它,这样我们就可以避免使用静态属性是浪费内存和处理时间的。使用
IsStackable
接口标记可堆栈的效果如何然后
if(effect is IsStackable){…}
?这是检查对象是否是可堆栈的,对吗?由于DerivedEffect.CreateEffect(obj)是一个静态函数,因此它没有要检查的对象。好的,在这种情况下,因为我们正在创建一个对象,所以检查它似乎有点奇怪,因为所讨论的bool实际上是类的特性,而不是一个特定的对象。我们还可以想象这样的情况,可能基于类的一个特性,我们不想实例化效果,然后实例化效果只是为了检查它,这样我们就可以避免使用静态属性是对内存和处理时间的浪费。这如何解决共享代码以根据效果类型(可堆叠或不可堆叠,可能基于以后的最大堆栈数)添加效果的问题?我想我失去了它,因为我是不是可以堆叠的。那是什么?对象何时可堆叠,何时不可堆叠?每种类型的效果(原始设计中的每个派生类)要么可堆叠,要么不可堆叠(意味着同一游戏对象上可以同时存在多个效果,要么不存在)。因为它是这种类型的属性,所以我认为静态bool是有意义的,但我没有看到一种方法可以让这种设计工作。不,静态不适合这样做。在
DerivedEffect
脚本中有一个公共变量,用于确定它是否“可堆叠”。当您想要查询使用
GetComponent
获取
DerivedEffect
脚本时,请使用检查其中的公共变量。有时我们可能没有要检查的实例对象,例如,如果我们添加了“castable”属性设置为“效果”或类似的属性,该属性决定了咒语可以在何处减少这些效果。在这种情况下,我们需要检查类型(类),看看实例化是否有意义,并且没有实际的对象来检查公共变量。信息技术
public static virtual Effect CreateEffect(GameObject obj)
{
    //T is somehow magically the type of the class you called this function on
    if(!T.IsStackable()) {
        //delete all components of type T on obj
    }
    T effect = obj.AddComponent<T>();
    return effect;
}