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
有没有一种优雅的方法可以在C#中实现这种模板方法或类似策略的模式?_C#_Design Patterns - Fatal编程技术网

有没有一种优雅的方法可以在C#中实现这种模板方法或类似策略的模式?

有没有一种优雅的方法可以在C#中实现这种模板方法或类似策略的模式?,c#,design-patterns,C#,Design Patterns,我正在努力决定构造一些代码的最佳方式。我承认这可能有些过火,而且正在变成一种更具学术性而非实用性的东西。有时候你就是无法控制自己 让我设计一个简单的例子: 假设您有如下类/接口: interface IProcessedPhoto { } interface IPhotoProcessor { IProcessedPhoto Process(byte[] bytes); void Alter(IProcessedPhoto processedPhoto); } class P

我正在努力决定构造一些代码的最佳方式。我承认这可能有些过火,而且正在变成一种更具学术性而非实用性的东西。有时候你就是无法控制自己

让我设计一个简单的例子:

假设您有如下类/接口:

interface IProcessedPhoto { }

interface IPhotoProcessor
{
    IProcessedPhoto Process(byte[] bytes);
    void Alter(IProcessedPhoto processedPhoto);
}

class PhotoProcessedWithAMethod : IProcessedPhoto { }

class PhotoProcessedWithBMethod : IProcessedPhoto { }

class AProcessor : IPhotoProcessor
{ 
    IProcessedPhoto Process(byte[] bytes);  // Returns PhotoProcessedWithAMethod 
    void Alter(IProcessedPhoto processedPhoto)
    {
        var casted = processedPhoto as PhotoProcessedWithAMethod;
        // a "B" would crash here.
    }
}

class BProcessor : IPhotoProcessor
{ 
    IProcessedPhoto Process(byte[] bytes);  // Returns PhotoProcessedWithBMethod  
    void Alter(IProcessedPhoto processedPhoto)
    {
        var casted = processedPhoto as PhotoProcessedWithBMethod;
        // an "A" would crash here.
    }
}

class Algorithm
{
    void DoStuff()
    {
        var processor = ProcessorFactory.CreateProcessor(//stuff);
        var processedPhoto = processor.ProcessPhoto(new byte[100]);
        processor.Alter(processedPhoto);
    }
}
基本上,我希望DoStuff()方法创建一种图像处理器,并调用适当的处理方法。然而,不管界面如何建议,该过程只在适当类型的IProcessedPhoto上工作(A和B照片不可互换,它们只是具有相似的方法名称)。我的实际代码更复杂,因为每个处理器都有几个特定于它们的类,并且不可互换,但我希望像模板方法一样执行相同的“逻辑”操作集

var artifactA = processor.DoA();
var artifactB = processor.DoB();
var final = processor.Process(artifactA, artifactB);

我希望这能解释它。

在我看来,您的
IProcessedPhoto
/
IPhotoProcessor
抽象太笼统了,至少就您描述的目的而言

您可以为每个photo类和处理器创建派生接口(例如,
IProcessedPhotoA
/
IPhotoProcessorA
,也可以为
B
)并调整代码,以便仅将实现所需接口的照片(
A
B
)传递给给定的处理器

我不确定这是否是整个代码库的最佳解决方案(我看不到)。我的建议是基于你的帖子:

然而,不管界面如何建议,该过程只对适当类型的IProcessedPhoto起作用(A和B照片不可互换,它们只是具有相似的方法名称)


如果它们不能互换供
光处理器使用,您的代码就不应该这样对待它们。

我会尝试将Alter方法放在IProcessedPhoto接口上,然后返回一个可以正确更改已处理照片的实现。注:您也可以将其连接到处理器,并在需要时使用其中的方法(未显示)

用作:

var processor = new PhotoProcessor();
var photoA = processor.Process( bytes, PhotoProcessingMethod.A );
photoA.Alter();

您可以使用泛型将
IProcessedPhoto
的特定实现绑定到
IPhotoProcessor
s:

interface IPhotoProcessor<TProcessedPhoto> 
  where TProcessedPhoto: IProcessedPhoto {

  TProcessedPhoto Process(byte[] bytes);
  void Alter(TProcessedPhoto processedPhoto);

}

...

class AProcessor : IPhotoProcessor<PhotoProcessedWithAMethod> { ... }

class BProcessor : IPhotoProcessor<PhotoProcessedWithBMethod> { ... }
处理器接口 其中t处理照片:i处理照片{ TProcessedPhoto进程(字节[]字节); void Alter(TProcessedPhoto processedPhoto); } ... 类处理器:IPhotoProcessor{…} 类B处理器:IPhotoProcessor{…}
缺点是,您的工厂也需要以下信息:

ProcessorFactory.CreateProcessor<PhotoProcessedWithAMethod>(/*stuff*/); 
ProcessorFactory.CreateProcessor(/*stuff*/);

我同意最后一点-事实上,这是我不喜欢编写的代码的主要原因。谢谢,我正在尝试根据我的代码调整此解决方案,看看它是否有效。正如你所说的,我不确定实际代码的复杂性是否会使这项工作达到最佳效果。谢谢,我正在尝试这一途径。我不喜欢它的一点(我认为您指出了这一点)是CreateProcessor返回的对象除了对象之外没有共同的祖先。如果不转换为更通用的代码,我就无法编写与As或Bs(但不能同时使用两者)一起工作的代码,在这种情况下,我又回到了开始的地方。您可以从工厂返回
iPhoneProcessor
。但是工厂方法本身需要该类型参数;强制客户机知道要为类型参数使用哪个值。更好的方法是将整个交互封装在另一个对象中,客户机不需要担心
过程
方法的返回值。
ProcessorFactory.CreateProcessor<PhotoProcessedWithAMethod>(/*stuff*/);