긴 소프트웨어 아키텍처 질문을 그래프로앞서
선명도 편집 : 나는 객체 그래프에 NodeA
, NodeB
같은 유형으로 구성 객체 그래프를, ... 변환하려고 그 *My*NodeA
, *My*NodeB
... 등으로 구성되며 그 반대의 경우도 마찬가지입니다. NodeX
유형의 등록 정보는 MyNodeX
유형의 유사한 등록 정보에 해당하지만 대부분의 경우 이 아니며은 사소한 할당입니다.
이 같은 두 개의 유사한 클래스 구조가있는 경우 :
// pure model, i.e. minimal information that is convenient for storage
abstract class Node
{
public int BaseProperty { get; set; }
public NodeCollection Children { get; private set; } // : Collection<Node>
}
class NodeA /* NodeB, NodeC ... */ : Node
{
public int DerivedAProperty { get; set; }
}
및
// objects that are convenient for being used by the application
abstract class MyNode
{
public int MyBaseProperty { get; set; }
public MyNodeCollection Children { get; private set; } // : Collection<MyNode>
}
class MyNodeA /* MyNodeB, MyNodeC ... */ : MyNode
{
public int MyDerivedAProperty { get; set; }
}
을, 나는의 객체 그래프로 변환해야
NodeX
중 하나에 입력
MyNodeX
유형 또는 모든에서
NodeX
클래스 중 하나를 변경하지 않고 그 반대로,
, 나는 나 자신이 정기적으로이 패턴을 사용하여 발견했습니다 NodeX -> MyNodeX
// USAGE/external code
Node node = ...
MyNode myNode = MyNode.Load(node, ARGS); // static factory
abstract class MyNode
{
...
// factory
public static MyNode Load(Node node, ARGS)
{
var type = node.GetType();
MyNode myNode;
// no 'is' usage because NodeB could be derived from NodeC etc.
if (type == typeof(NodeA))
myNode = new MyNodeA(ARGS); // arbitrary ctor
else if (...)
...
myNode.Load(Node);
return myNode
}
public virtual void Load(Node node)
{
this.MyBaseProperty = node.BaseProperty;
foreach (var child in node.Children)
this.Children.Add(MyNode.Load(child, this.ARGS));
}
}
class MyNodeA : MyNode
{
...
public override void Load(Node node)
{
var m = (NodeA)node; // provoke InvalidCastException if coding error
base.Load(node);
this.MyDerivedAProperty = m.DerivedAProperty;
}
}
MyNodeX -> NodeX
// USAGE/external code
MyNode myNode = ...
Node node = myNode.Commit();
abstract class MyNode
{
...
// 'kind of' factory
public abstract Node Commit();
public virtual Commit(Node node)
{
node.BaseProperty = this.MyBaseProperty;
foreach (var child in this.Children)
node.Children.Add(child.Commit());
}
}
class MyNodeA : MyNode
{
...
public override Node Commit()
{
var m = new NodeA(); // "factory" method for each type
this.Commit(m);
return m;
}
public override void Commit(Node node)
{
var m = (NodeA)node; // provoke InvalidCastException if coding error
base.Commit(node);
m.DerivedAProperty = this.MyDerivedAProperty;
}
}
나는이 접근 방식을 여러 번 성공적으로 사용했으며, 클래스에 추가해야하는 메소드가 곧 바뀌고 외래 코드도 마찬가지이기 때문에 일반적으로 좋아합니다. 또한 base.Load(node)
/base.Commit(node)
을 호출하여 코드 중복을 방지합니다. 그러나, 나는 정말로 그/그 밖의 정적 인 Load
팩토리 메소드의 사닥다리를 좋아하지 않는다. > MYNODE (Load
)의 경우, 그것은 MYNODE에 얼마나 유사 - -> 노드 (Commit
)의 경우
나는 노드에 대한 각 유형에 공장 방법을 선호한다. 그러나 static
과 virtual
은 분명히 약간 문제가 있습니다. 나는 또한 지금해야만하는 두 개의 캐스트를하지 않는 것을 선호합니다.
어떻게 든 이런 일이 가능합니까?
탐색을 허용하고 방문자 패턴을 사용하여 한 유형에서 다른 유형으로 변환 할 수있는 데이터 구조를 사용합니다 (죄송합니다. 정성을 다할 시간이 없습니다 - 음식). –
NodeA에서 NodeB? – sircodesalot
@sircodesalot 'NodeA','NodeB' ...와 같은 타입으로 구성된 객체 그래프를'* My * NodeA','* My * NodeB'와 같은 타입으로 구성된 객체 그래프로 변환하려고합니다. ., 그 반대. – dialer