我有一个架构问题,我无法独自解决。
我的问题是,在某个地方,我总是以打开类型或一组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();
}
}
您有什么想法或任何模式名称来解决我的问题吗?
非常感谢。
答案 0 :(得分:1)
假设您无法修改每个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);
答案 1 :(得分:0)
为什么要完全使用ThingTransformer?
public interface IThing
{
string CommonProperty { get; }
string Transform();
}
public class FirstThing : IThing
{
public string CommonProperty { get; }
public string Transform() => this.CommonProperty + this.FirstParticularProperty;
public string FirstParticularProperty { get; }
}
public class SecondThing : IThing
{
public string CommonProperty { get; }
public string Transform() => this.CommonProperty + this.SecondParticularProperty;
public string SecondParticularProperty { get; }
}
答案 2 :(得分:0)
恕我直言,每个IThing都应该知道如何进行自我转换。为什么在构造IThing时不注入正确类型的IThingTransormStrategy?