Closed. This question is opinion-based。它当前不接受答案。
                            
                        
                    
                
                            
                                
                
                        
                            
                        
                    
                        
                            想改善这个问题吗?更新问题,以便editing this post用事实和引用来回答。
                        
                        20天前关闭。
                                                                                            
                
        
我有一个架构问题,我无法独自解决。


我有一系列实现相同接口(IThing)的对象。
我想对“ IThing”集合的每个对象应用转换。
转换取决于接口的实现。
接口实现的转换封装在一个类中。 (策略模式)


我的问题是,在某个地方,我总是以打开类型或一组if-is-cast结束,这对我来说破坏了代码的可扩展性。

这是一个例子:

    public interface IThing
{
    string CommonProperty { get; }
}

public class FirstThing : IThing
{
    public string CommonProperty { get; }
    public string FirstParticularProperty { get; }
}

public class SecondThing : IThing
{
    public string CommonProperty { get; }
    public string SecondParticularProperty { get; }
}

public interface IThingTransformStrategy<T> where T : IThing
{
    string Transform(T thing);
}

public class FirstThingTransformStrategy : IThingTransformStrategy<FirstThing>
{
    public string Transform(FirstThing thing)
    {
        return thing.CommonProperty + thing.FirstParticularProperty;
    }
}

public class SecondThingTransformStrategy : IThingTransformStrategy<SecondThing>
{
    public string Transform(SecondThing thing)
    {
        return thing.CommonProperty + thing.SecondParticularProperty;
    }
}

public class ThingTransformer
{
    private FirstThingTransformStrategy _firstThingTransformStrategy = new FirstThingTransformStrategy();
    private SecondThingTransformStrategy _secondThingTransformStrategy = new SecondThingTransformStrategy();

    public string TransformThing(IThing thing)
    {
        //Here is the issue
        if (thing is FirstThing) return _firstThingTransformStrategy.Transform((FirstThing) thing);
        if (thing is SecondThing) return _secondThingTransformStrategy.Transform((SecondThing) thing);
        throw new NotImplementedException();
    }
}


您是否有任何想法或任何模式名称来解决我的问题?

非常感谢。

最佳答案

假设您不能修改每个IThing来知道如何进行自我转换,那么我将介绍访问者模式。

public class ThingTransformer
{
    public string Transform(FirstThing thing) => _firstThingTransformStrategy.Transform(thing);
    public string Transform(SecondThing thing) => _secondThingTransformStrategy.Transform(thing);
}

public interface IThing
{
    // ...
    string Transform(ThingTransformer transformer);
}

public class FirstThing : IThing
{
    // ...
    public string Transform(ThingTransformer transformer) => transformer.Transform(this);
}

public class SecondThing : IThing
{
    // ...
    public string Transform(ThingTransformer transformer) => transformer.Transform(this);
}


然后您可以编写:

var thing = new FirstThing();
var transformer = new ThingTransformer();
var transformed = thing.Transform(transform);


这具有编译时安全性的优点:如果添加IThing的新实现,则最终会出现编译器错误,直到将新方法添加到ThingTransformer为止。

如果要稍微抽象一些东西,请将ThingTransformer隐藏在接口后面,并使IThing采用该接口代替具体的ThingTransformer



更一般而言,您可以编写通用访问者:

public interface IThingVisitor<T>
{
    T Accept(FirstThing thing);
    T Accept(SecondThing thing);
}

public interface IThing
{
    T Visit<T>(IThingVisitor<T> visitor);
}

public class FirstThing : IThing
{
    public T Visit<T>(IThingVisitor<T> visitor) => visitor.Accept(this);
}

public class SecondThing : IThing
{
    public T Visit<T>(IThingVisitor<T> visitor) => visitor.Accept(this);
}

public class ThingTransformer : IThingVisitor<string>
{
    public string Accept(FirstThing thing) => _firstThingTransformStrategy.Transform(thing);
    public string Accept(SecondThing thing) => _secondThingTransformStrategy.Transform(thing);
}


然后:

var thing = new FirstThing();
var transformer = new ThingTransformer();
var transformed = thing.Visit(transformer);

09-27 00:53