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

问题描述

| 我正在尝试确定构建某些代码的最佳方法。我承认这可能太过分了,而且正在变成一种学术性而非实用性的东西。有时候你就是无法自救。 让我想一个简单的例子: 假设您具有以下类/接口:
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()方法创建一种图像处理器,并调用适当的Process方法。但是,尽管界面显示了建议,但Process只能在适当类型的IProcessedPhoto上运行(A和B照片不可互换,它们具有相似的方法名称)。我的实际代码更加复杂,因为每个处理器都有几个特定于它们的类,并且不能互换,但是我想执行相同的一组“逻辑”操作,例如模板方法
var artifactA = processor.DoA();
var artifactB = processor.dob();
var final = processor.Process(artifactA,artifactB);
我希望能解释一下。     

解决方法

        您可以使用泛型将
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> { ... }
缺点是您的工厂还需要以下信息:
ProcessorFactory.CreateProcessor<PhotoProcessedWithAMethod>(/*stuff*/); 
    ,        在我看来,您的
IProcessedPhoto
/
IPhotoProcessor
抽象过于笼统,至少出于您描述的目的。 您可以为每个照片类和处理器创建派生接口(例如
IProcessedPhotoA
/
IPhotoProcessorA
,对于
B
相同),并调整代码,以便仅将实现所需接口(interface11ѭ或
B
)的照片传递给给定处理器。 。 我不确定这是否是您整个代码库的最佳解决方案(我看不到)。我的建议是基于您的这篇文章:   但是,尽管界面显示了建议,但Process仅适用于适当类型的IProcessedPhoto(A和B照片不可互换,它们具有相似的方法名称) 如果它们不能互换以供ѭ13使用,则您的代码不应这样对待它们。     ,        我很想将Alter方法放在IProcessedPhoto接口上,然后返回一个可以正确更改处理后的照片的实现。请注意,您也可以将其连接到处理器,并根据需要使用其中的方法(未显示)。
public enum PhotoProcessingMethod { A,B }

public interface IProcessedPhoto
{
     void Alter();
}

public AProcessedPhoto : IProcessedPhoto
{
     ...

     public void Alter()
     {
        ... alter an A...
     }
}

public BProcessedPhoto : IProcessedPhoto
{
     ...
     public void Alter()
     {
      ... alter a B...
    }
}

public interface IPhotoProcessor
{
     IProcessedPhoto Process(byte[] bytes,PhotoProcessingMethod method);
}

public class PhotoProcessor : IPhotoProcessor
{
     public IProcessedPhoto Process(byte[] bytes,PhotoProcessingMethod method)
     {
          IProcessedPhoto photo;
          switch (method)
          {
              case PhotoProcessingMethod.A:
                   photo = new AProcessedPhoto(bytes);
                   break;
              case PhotoProcessingMethod.B:
                   photo = new BProcessedPhoto(bytes);
                   break;
          }
          ...

          return photo;
     }
}
用作:
var processor = new PhotoProcessor();
var photoA = processor.Process( bytes,PhotoProcessingMethod.A );
photoA.Alter();
    

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...