假设我们有一个对象代表一块硬件的配置.为了论证,温度控制器(TempController).它包含一个属性,即设定点温度.
我需要将此配置保存到文件中以便在其他设备中使用.文件格式(FormatA)是一成不变的.我不希望TempController对象知道文件格式......它与该对象无关.所以我创建了另一个对象"FormatAExporter",它将TempController转换为所需的输出.
一年后,我们制作了一个新的温度控制器,我们称之为"AdvancedTempController",它不仅具有设定值,而且还具有速率控制,这意味着还有一两个属性.还发明了一种新的文件格式来存储这些属性......我们称之为FormatB.
两种文件格式都能够表示两种设备(如果缺少设置,则假设AdvancedTempController具有合理的默认值).
所以这就是问题所在:不使用'isa'或其他"作弊"方式来确定我拥有的对象类型,FormatBExporter如何处理这两种情况?
我的第一直觉是在每个温度控制器中都有一个方法,可以为该类提供客户导出器,例如TempController.getExporter()和AdvancedTempController.getExporter().这不能很好地支持多种文件格式.
我想到的唯一另一种方法是在每个温度控制器中有一个方法,它返回一个属性列表及其值,然后格式化程序可以决定如何输出它们.它有用,但这看起来很复杂.
更新:进一步的工作,后一种方法并没有真正奏效.如果你的所有类型都很简单,但是如果你的属性是对象,那么你最终只是将问题推到一个级别......你被迫返回一对String,Object值,导出器必须知道什么对象实际上是要利用它们.所以它只是把问题推到了另一个层面.
对于我如何保持这种灵活性有什么建议吗?
您可以做的是让 TempController 负责使用通用存档器来持久保存自身。
class TempController
{
private Temperature _setPoint;
public Temperature SetPoint { get; set;}
public ImportFrom(Archive archive)
{
SetPoint = archive.Read("SetPoint");
}
public ExportTo(Archive archive)
{
archive.Write("SetPoint", SetPoint);
}
}
class AdvancedTempController
{
private Temperature _setPoint;
private Rate _rateControl;
public Temperature SetPoint { get; set;}
public Rate RateControl { get; set;}
public ImportFrom(Archive archive)
{
SetPoint = archive.Read("SetPoint");
RateControl = archive.ReadWithDefault("RateControl", Rate.Zero);
}
public ExportTo(Archive archive)
{
archive.Write("SetPoint", SetPoint);
archive.Write("RateControl", RateControl);
}
}
Run Code Online (Sandbox Code Playgroud)
通过保持这种方式,控制器不关心实际值如何存储,但您仍然可以很好地封装对象的内部结构。
现在您可以定义一个所有存档类都可以实现的抽象 Archive 类。
abstract class Archive
{
public abstract object Read(string key);
public abstract object ReadWithDefault(string key, object defaultValue);
public abstract void Write(string key);
}
Run Code Online (Sandbox Code Playgroud)
FormatA 归档程序可以以一种方式执行此操作,而 FormatB 归档程序可以以另一种方式执行此操作。
class FormatAArchive : Archive
{
public object Read(string key)
{
// read stuff
}
public object ReadWithDefault(string key, object defaultValue)
{
// if store contains key, read stuff
// else return default value
}
public void Write(string key)
{
// write stuff
}
}
class FormatBArchive : Archive
{
public object Read(string key)
{
// read stuff
}
public object ReadWithDefault(string key, object defaultValue)
{
// if store contains key, read stuff
// else return default value
}
public void Write(string key)
{
// write stuff
}
}
Run Code Online (Sandbox Code Playgroud)
您可以添加另一个控制器类型并将其传递给任何格式化程序。您还可以创建另一个格式化程序并将其传递给任何控制器。
| 归档时间: |
|
| 查看次数: |
376 次 |
| 最近记录: |