Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Design patterns 设计模式以避免在转换/转换期间切换大小写类型_Design Patterns - Fatal编程技术网

Design patterns 设计模式以避免在转换/转换期间切换大小写类型

Design patterns 设计模式以避免在转换/转换期间切换大小写类型,design-patterns,Design Patterns,我正在尝试实现一个首选项系统,程序员可以在其中指定首选项名称、类型(布尔、整数、字符串等)以及可选的默认值。我想了一段时间,但没有想到一个通用的解决方案来存储到磁盘或从磁盘加载。我希望设计足够通用,能够处理多种格式(即文本文件、Windows注册表或Apple的属性列表)。简单的解决方案是为每种存储格式制作转换器,并在已经选择了存储格式的情况下在线路的某个位置制作转换器,遍历首选项并在其类型上切换大小写 有人告诉我,在一个类型上执行切换案例不是一个好的解决方案,我明白为什么:如果我添加了一个类型

我正在尝试实现一个首选项系统,程序员可以在其中指定首选项名称、类型(布尔、整数、字符串等)以及可选的默认值。我想了一段时间,但没有想到一个通用的解决方案来存储到磁盘或从磁盘加载。我希望设计足够通用,能够处理多种格式(即文本文件、Windows注册表或Apple的属性列表)。简单的解决方案是为每种存储格式制作转换器,并在已经选择了存储格式的情况下在线路的某个位置制作转换器,遍历首选项并在其类型上切换大小写

有人告诉我,在一个类型上执行切换案例不是一个好的解决方案,我明白为什么:如果我添加了一个类型,我需要去修改所有这些切换案例块。那么我应该怎么做呢?通常的答案是让被检查类型的对象实现一个公共接口,并知道如何自己执行操作

但这对我来说似乎很荒谬,因为有一个偏好值知道如何将自己存储在文本文件、Windows注册表和Apple属性列表中。这就解决了问题。如果我添加了一个新的变压器,我需要去修改所有的类型,而不是添加一个新的类型要求我去修改变压器


我想这是一个常见的设计问题,但我找不到任何好的解决方案。

访问者模式的经典用法。虽然您有时会看到更一般地表达模式,但下面是一些通过访问者模式表示的持久性层的psuedo代码

请注意,首选项不需要知道如何保存自己,它们只需要将自己传递给存储机制:

abstract BasePreference
{
    abstract Persist(PreferenceStorage ps);
}


NumericPreference : BasePreference
{
   string Name;
   int Value;
   int Default

   Persist(PreferenceStorage ps)
   {
      ps.Save(this);
   }

}


StringPreference : BasePreference
{
   string Name;
   string Value;
   string Default

   Persist(PreferenceStorage ps)
   {
      ps.Save(this);
   }   
}


DateRangePreference : BasePreference
{
   string Name;
   DateTime StartOfRange;
   DateTime EndOfRange;
   DateTime DefaultStartOfRange;
   DateTime DefaultEndOfRange;

   Persist(PreferenceStorage ps)
   {
      ps.Save(this);
   }   
}
接下来,PreferenceStorage利用方法重载允许为每个pref子类型运行单独的代码。类型上没有开关块:

abstract PreferenceStorage 
{
   abstract void Save(NumericPreference pref);
   abstract void Save(StringPreference pref);
   abstract void Save(DateRangePreference pref);   
}
最后,PreferenceStorage的子类负责机制或保存数据:

XmlPreferenceStorage : PreferenceStorage
{
   void Save(NumericPreference pref)
   {
      // save number to xml 
   }

   void Save(StringPreference pref)
   {
      // save string to xml 
   }   

   void Save(DateRangePreference pref)
   {
      // save date range to xml 
   }      
}



RegistryPreferenceStorage : PreferenceStorage
{
   void Save(NumericPreference pref)
   {
      // save number to registry 
   }

   void Save(StringPreference pref)
   {
      // save string to registry 
   }   

   void Save(DateRangePreference pref)
   {
      // save date range to registry 
   }      
}

(Uggg,为什么格式设置得这么糟糕?很抱歉缩进不好,通常是很好的代码格式设置)

现在格式设置看起来更好了…我想这只是个小问题,谢谢。我听说过“访客模式”这个名字,但不知道它的具体内容。这并不是说这个名字能让它跳出来解决这个问题。顺便说一句,Wikipedia动机的例子基本上描述了与我所遇到的问题完全相同的问题。同意,访问者有一个非直观的名称,并且在其通用形式中,所使用的方法名称同样不透明。