我已经实现了一个基本的图形类(不是在“绘图”中而是在“网络”中!),这将用于基本的图论任务。(见下面汇总的头文件片段)除了一般的图形功能外,它还实现了在三维空间中进行节点定位的功能。我想将这个扩展的3d功能分离成一个子类,结果是:轻型通用类(MyGenericGraph,MyGenericGraphNode, MyGenericGraphEdge)重专业子班(My3DGraph, My3DGraphNode,My3DGraphEdge)到目前为止,理论上,还不错。问题:我必须确保(最好是在编译时),不能将通用的MyGenericGraphNodes添加到Excel化的My3DGraph,因为它高度依赖于My3DGraphNode中添加的3D逻辑。(而一般的MyGenericGraph根本不在乎。)核心问题很简单:我无法从MyGenericGraph重写这些方法:- (void)addNode:(MyGenericGraphNode *)aNode;- (void)removeNode:(MyGenericGraphNode *)aNode;在我的子类my3dGraph中使用这些方法:- (void)addNode:(My3DGraphNode *)aNode;- (void)removeNode:(My3DGraphNode *)aNode;到目前为止,我已经提出了三种可能的解决方案,但在提出任何一种解决方案之前,我想听听对它们的一些看法。(希望在路上能省去一些不可预见的麻烦)我想知道,我是否遗漏了另一个更好的解决方案或设计模式?或者如果没有:你会选择我的哪一个解决方案?我很想听听你对此的意见。可能的解决方案1添加一个抽象类MyAbstractGraph,它基本上与我当前实现的MyGenericGraph的通用部分相同(见下文),但是缺少任何节点添加/移除方法。MyGenericGraph和My3DGraph只是MyAbstractGraph的子类。虽然MyGenericGraph只实现了缺少的节点添加/移除方法,My3DGraph将进一步实现所有3d空间功能。两者都需要各自的节点类类型。(同样适用于MyGenericGraphNode和MyGenericGraphEdge及其3D对应)这个解决方案的问题:它会给一个相当简单的问题增加大量的复杂性。此外,由于My3DGraph应该能够处理My3DGraphNodes和MyGenericGraphNodes,我必须将MyGenericGraph的方法实现为:- (void)addNode:(MyAbstractGraphNode *)aNode;`但是My3DGraph的方法是:- (void)addNode:(My3DGraphNode *)aNode;另外,和我的通用图一样,它不接受三维节点。但这将不必要地公开抽象类。可能的解决方案2真正且简单的子类+将MyGenericGraphNode/My3DGraphNode分配移到MyGenericGraph/My3DGraph中,得到类似于:- (MyGenericGraphNode *)newNode;的内容,它将分配并返回正确类型的节点,并立即将其添加到图中。然后,将完全去掉- (void)addNode:(MyGenericGraphNode *)aNode;,除了从图本身添加节点之外,没有机会添加节点(因此确保适当的类成员资格)。这个解决方案的问题:虽然它不会给类增加任何值得注意的复杂性,但另一方面,基本上让我再次陷入同样的困境,我想说,我想把一个节点从一个图移动到另一个图来增加我的My3DGraph的功能。类应该能够处理对象,不管是谁创建的,为什么创建的。可能的解决方案3真正简单的子类+为3D节点添加特殊方法和禁用泛型方法,如:- (void)addNode:(MyGenericGraphNode *)aNode { [self doesNotRecognizeSelector:_cmd];}- (void)add3DNode:(My3DGraphNode *)aNode { //bla}这个解决方案的问题:泛型[a3DGraph addNode:aNode]方法仍然会出现在xcode的auto-complete中,编译时无声地传递,但是在运行时意外地抛出异常。经常头痛。可能的解决方案4我的图的纯简子类和节点和边的泛型类,但是在节点类中有一个额外的IVAR指针My3DUnit *dimensionalUnit:(默认为MyGrand的NIL),它实现了所有的逻辑和属性,并为节点类提供了3D功能。My3DUnit只需安静地创建(例如位置(0,0,0))并附加到通用节点,以防它们被添加到三维图形中,从而使其兼容。反之亦然,如果一个DL3DUnit的节点被添加到一个通用图中,它只是保持它的连接并添加节点。头文件以下是我的课程标题:@interface MyGraph : NSObject { // properties: NSMutableSet *nodes; //... //extended 3D properties:double gravityStrength; //...}// functionality:- (void)addNode:(MyGraphNode *)aNode;- (void)removeNode:(MyGraphNode *)aNode;//...//extended 3D functionality:- (double)kineticEnergy;//...@end@interface MyGraphNode : NSObject { // properties: MyGraph *graph; NSMutableSet *edges; //... //extended 3D properties: My3DVector position; //...}// properties:@property (nonatomic, readonly) MyGraph *graph;@property (nonatomic, readonly) NSSet *edges;@property (nonatomic, readonly) NSSet *neighbors;@property (nonatomic, readonly) NSUInteger degree;//...//extended 3D properties@property (nonatomic, assign) My3DVector position;//...// functionality:- (void)attachToGraph:(MyGraph *)aGraph;- (void)detachFromGraph;- (void)addNeighbor:(MyGraphNode *)aNode;- (void)removeNeighbor:(MyGraphNode *)aNode;- (BOOL)hasNeighbor:(MyGraphNode *)aNode;- (NSSet *)neighbors;- (NSUInteger)degree;//...//extended 3D functionality:- (double)distanceToNode:(DLGraphNode *)aNode;//...@end@interface MyGraphEdge : NSObject { // properties: MyGraphNode *predecessor; MyGraphNode *successor; //...}// properties:@property (nonatomic, readonly) MyGraphNode *predecessor;@property (nonatomic, readonly) MyGraphNode *successor;//...// functionality:- (id)initWithPredecessorNode:(MyGraphNode *)predecessorNode successorNode:(MyGraphNode *)successorNode;+ (MyGraphEdge *)edgeWithPredecessorNode:(MyGraphNode *)predecessorNode successorNode:(MyGraphNode *)successorNode;- (BOOL)hasNeighbor:(MyGraphNode *)aNode;- (BOOL)hasSuccessor:(MyGraphNode *)aNode;- (BOOL)hasPredecessor:(MyGraphNode *)aNode;@end这就是我的图现在是如何实现的。显然还有很多,但你应该明白。(正如您可能已经注意到的,MyGigCIPKORKEST目前没有实现3D空间功能,但它可能在将来,比如计算它的中心点,例如,因此我已经把它包含在这里。)[编辑:添加了受Ughoavgfhw启发的解决方案4;修复了解决方案1中的错误,抱歉:(] 最佳答案 快速肮脏的解决方案:在重新分析我的类结构和发现一些以前未预见到的潜在缺陷,在未来的发展对我的计划图类家庭,我已经得出结论,与我提出的解决方案4,但伴随着它的一些重大重组(见附图简化ER图)。我的计划是,不要使用重多用途的UBER类,有多个单用途组件(如果构造良好)可以组合成各种特殊用途(和相对轻量级)的工具集。简单继承的潜在陷阱:如果我在cc的一个子类中实现维度特征集,那么这就使得我基本上不可能轻松创建更具体的图子类(对于专门的树),可以是轻量级的和泛型的(如MyGenericGraph)或维(如cc)。对于MyGenericGraph类(例如树分析),我必须将My3DGraph子类化。对于MyGenericTree(例如树显示),但是我必须将MyGenericGraph子类化。因此,My3DTree不能从My3DGraph继承任何逻辑。我会多余地实现维度特征。很糟糕。相当糟糕。建议的类结构架构:完全摆脱任何“维味儿”类。用基本的和必需的逻辑严格保持类的数据结构。介绍MyVIEX类,如果需要的话,将维度属性和方法提供给节点(通过将My3DTree IVAR添加到MyGenericTree(默认为NIL))。这也使得在简单的点云容器中重用它们变得更加容易,这对于改进我的力驱动布局算法应该是有用的。将任何对图形数据结构不严格必要的逻辑委托给特殊用途的帮助类。因此,MyVertex *vertex将负责任何特定于可视图形布局的逻辑。由于我的链式继承链和模块化,子类将是快速和容易的。利用外部MyGraphNode也允许我放松图节点的子集,而不仅仅是一个完整的图,因为My3DGrad会做到这一点。MyVertexCloud将只不过是基本上是一组节点的包装器(所有相同的图)。它的子类可以在聚类隶属度准则和算法中更具体。从整个图形中获取MyGraphNodeClusterRelaxer就像调用MyGraph一样简单,从这里可以通过MyGraphNodeClusterRelaxer获得MyGraphNodeCluster。相反的(对于后者)是不可能的,因为可怕的原因。(简化)实体关系模型:
08-18 02:15