【发布时间】:2013-11-05 22:34:41
【问题描述】:
我正在使用 Unity3D 和 C# 创建一个伪游戏内操作系统(有点野心)
请注意,这是一个纯粹的设计问题,您可以在不了解 Unity 的情况下回答。
这是我所拥有的:
摘要FILE,有孩子:
TextFileMediaFileImageFile
还有一个摘要Application,有孩子:
TextViewerMediaPlayerImageViewer
显然,TextViewer 应该打开 TextFiles,MediaPlayer 应该打开 MediaFiles 和 ImageViewer 应该打开 ImageFiles。
现在,我想了想,应该把who-opens-whom信息放在哪里?
我应该让每个文件自己打开吗?通过在FILE 中创建抽象Open,并在子文件中覆盖它? - 我认为这没有意义,因为文件并不真正知道如何打开自己,它是知道如何打开文件的应用程序。比如一个pdf文件,如果你没有pdf阅读器(Adobe之类的)是打不开pdf的。
这意味着TextViewer 应该有一个Open(TextFile text) 方法,MediaPlayer 应该有一个Open(MediaFile media) 和ImageViewer 应该有一个Open(ImageFile image) 方法。
这可以通过在Application 的声明中使用泛型来实现,例如:
public abstract class Application<T> where T : FILE
{
public abstract void Open(T file);
}
然后:
public class TextViewer : Application<TextFile>
{
public override void Open(TextFile file)
{
Console.WriteLine("TextViewer opening text file...");
}
}
public class MediaPlayer : Application<MediaFile>
{
public override void Open(MediaFile file)
{
Console.WriteLine("MediaPlayer opening media file...");
}
}
public class ImageViewer : Application<ImageFile>
{
public override void Open(ImageFile file)
{
Console.WriteLine("ImageViewer opening image file...");
}
}
UML 图如下所示:
看起来不错...现在有趣的部分是,如何绑定/关联每种文件类型,并使用正确的应用程序打开它?即右键单击文本文件|获取选项列表:“打开”、“重命名”、“删除”等 |选择“打开”——接下来会发生什么?
我想出了一个想法,在FILE 和Application 之间建立一个中介 - 如果我们想一想,像 Windows 这样的真实操作系统是如何做到的? - 好吧,如果你开始 |默认程序 |将文件类型或协议与程序相关联。 - 你会看到一个字典类型列表,键(文件类型)和值(关联程序) - 所以我想这样做,创建一个字典,我用它注册,一个应用程序的文件类型。这就是我被困的地方......
首先,我应该在字典中查找什么类型的键和值? - 我想了一会儿,得出的结论应该是<Type, Application> - 但问题是,我不能只写Application,我必须指定通用的T参数:(
我破解了这一点,创建了一个中间类 App,然后让我的 Application<T> 继承自:
public abstract class App { }
public abstract class Application <T> : App where T : FILE { /* stuff... */ }
好的,现在我可以让我的字典是<Type, App>
public static class Mediator
{
static private TextViewer tv;
static private MediaPlayer mp;
static private ImageViewer iv;
static private Dictionary<Type, App> dic = new Dictionary<Type, App>();
static Mediator()
{
tv = new TextViewer();
iv = new ImageViewer();
mp = new MediaPlayer();
// register what we have
dic.Add(typeof(TextFile), tv);
dic.Add(typeof(MediaFile), mp);
dic.Add(typeof(ImageFile), iv);
}
static public void Open(FILE file)
{
App app = dic[file.GetType()];
if (app == null)
{
Console.WriteLine("No application was assigned to open up " + file);
return;
}
app. // here is where my hack falls short, no Open method inside App :(
}
}
糟糕,这完全没有用! - 如您所见,我尽力避免以下事情:
if (file is TextFile)
// open with text viewer
else if (file is MediaFile)
// open with media player
else if (file is ImageFile)
// open with image viewer
else if etc
这对我来说就像一场噩梦!
通过将我的应用程序设为单例,我可以避免所有麻烦,所以现在在每个文件中:
public class TextFile : FILE
{
public override void Open()
{
TextViewer.Instance.Open(this);
}
}
其余文件依此类推。但我不想那样做,我不想放弃使用单例!如果我希望我的 MediaPlayer 或 TextViewer 拥有多个实例而不是一个实例怎么办?
我已经为此苦苦挣扎了很长时间,我希望我能把我的问题说清楚。我只是想知道,将文件类型与正确的应用程序相关联如何以正确的方式工作(例如在 Windows 中) - 我怎样才能以优雅、强大的方式实现我所追求的? - 有没有我可以使用的设计模式? - 我上面所有的尝试,我想对了吗?我接近解决方案了吗?
非常感谢您提前提供的任何帮助。
【问题讨论】:
-
@terrybozzio:我考虑过标记 unity3d,但后来我发现几乎没有任何相关内容 - 这是一个纯粹的设计问题。这就是为什么我认为,操作系统更好。无论如何...
标签: c# inheritance polymorphism unity3d