有没有一种优雅的方法可以在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*/);