数据模型+行为架构设计

时间:2014-07-01 02:13:19

标签: design-patterns architecture

我无法发布图片,但我正在使用此模型制作文档工具。

我有对象(抽象)类和关系类和属性类。

所有这些都挂在上下文类中,我保留了环境变量,还有一个对象集合,一个属性集合和一个关系集合。

让对象从上下文继承是一个好主意吗?所以我可以将所有内置的功能和行为继承到所有对象和关系?

或者更好的做法是将它分开并创建一个基类(行为),其中上下文,对象,属性和关系将继承我想要流经对象的所有功能,并保留一组属性这个更高层(行为)可以扩展所有对象并根据需要添加属性吗?

我希望它足够清楚......发布图表会更容易,但我还不能。

这里有一个小伪代码来表明我的意思:

public abstract class Behaviour
{
    ToXML();
    JSonSerilize();
    Save();
    Display();
    Compare();
}


public abstract class Context : Behaviour
{
    public List<Object> Objects { get; set; }
    public List<Property> Properties { get; set; }
    public List<Relationship> Relationships { get; set; }
    AddObject();
}


public class Property : Context
{
    public Object ObjectRelated { get; set; }
}

public abstract class Object : Context
{
}

public abstract class Relationship : Context
{
        public Object Source { get; set; }

        public Object Target { get; set; }
}

OR

public abstract class Behaviour
{
    ToXML();
    JSonSerilize();
    Save();
    Display();
    Compare();
    public List<Property> Properties { get; set; }
}


public abstract class Context : Behaviour
{
    public List<Object> Objects { get; set; }
    public List<Relationship> Relationships { get; set; }
    AddProperty (Object, value) { base:Properties.Add}

}


public class Property : Behaviour
{
    public Object ObjectRelated { get; set; }
}

public abstract class Object : Behaviour
{
    AddProperty (Object, value) { base:Properties.Add}
}

public abstract class Relationship : Behaviour
{
     public Object Source { get; set; }

    public Object Target { get; set; }

    AddProperty (Object, value) { base:Properties.Add}
}

我非常喜欢第二种设计,其中所有对象(对象,关系,上下文)都可以在属性中进行扩展,但我不喜欢这样的事实:我必须将属性集合保留在上层类中(行为) ),似乎太紧密耦合了。 任何想法,利弊?

进一步详情:(谢谢NWard)

目标:用于记录工具的核心库。 我想要一个通用的核心库,我可以用它来实现不同的文档场景。 我希望分离这些对象如何在内存中保持,序列化和操作以及它的实际扩展/实现(2层)

要求: 我需要能够通过web服务/ odata / db / json持久/传输整个&#34;数据上下文类&#34;及其所有对象+属性及其关系。

  

即使应用程序中的每个类都需要动态生成   生成属性列表(为什么?)

因为我想生成一个核心对象类型,还有一个关系类型和一个数据上下文类型,能够在不改变其基础&#34;结构的情况下进行扩展。

实施示例如下:

public class FancyRectangle : Object
{
    public string Name { get { return this.GetPropertyValueString("Name"); } set { this.AddProperty("Name", value); } }
    public string Description { get { return this.GetPropertyValueString("Description"); } set { this.AddProperty("Description", value); } }
    public float Height { get { return this.GetPropertyFloat("Height"); } set { this.AddProperty("Height", value); } }
    public float Lenght { get { return this.GetPropertyFloat("Lenght"); } set { this.AddProperty("Lenght", value); } }
}

当然,所有这些对象都可以执行以下操作:

FancyRectangle rect1 = new FancyRectangle();

rect1.AddRelationship(rect2);
rect1.ToXml();
rect2.ToJson();

另外

  • context.Save()将所有对象,属性,关系持久化到数据库中,例如,我也希望能够序列化和反序列化整个&#34;数据上下文&#34;
  • 我想做Context1.Compare(Context2)和处理所有数据上下文对象(对象,属性和关系)的操作

我想在抽象类中实现这些行为,所以当Object类被实现时(即FancyRectangle类)我不必将这些常见的行为和属性编码到其中,这些行为和属性都是我想要的继承.ToXml(),. ToJson()

的一个实现

我希望这个核心库非常便于携带,并且可以轻松扩展,并且不会限制其实现。

此核心库可能会与读者,用户界面和演示者进行交互。

干杯

1 个答案:

答案 0 :(得分:2)

我发现你的继承结构很难理解。也许你理解其背后的动机对你更有意义,但是通过继承的面向对象模式通常通过 他们的超类来完成。属性,关系,上下文和对象是否真的是相同的 - 行为?我倾向于认为他们不是。但是,如果您有关于特定案例的更多具体细节,那将非常有用。

在进行面向对象设计时要记住的一组好的启发式算法是SOLID(http://en.wikipedia.org/wiki/SOLID_(object-oriented_design))。

由于您的继承结构非常广泛,您的设计未能通过单一责任原则和接口(抽象类)隔离原则。您的对象负责序列化自己,比较自己,保存自己和显示自己。这是很多责任!对于其他类来说,处理显示,数据持久性,比较等事情会更好 - 让对象保持其状态并且不了解应用程序的其他问题。这样,您可以更改 这些问题的实施方式,但您的对象不受影响。这使您的应用程序更清晰,更易于维护。

我会在这里考虑你的结构提出一种不同的方法。您希望使您的界面更小,更集中。即使你的应用程序中的每个类都需要一个动态生成的Properties列表(为什么?),这应该是一个非常低级的接口,也许是IPropertyHaving,所有其他接口都从这个接口继承 - 但没有任何其他功能。通过保持接口小,您不必担心这种紧密耦合的设计。但是,我建议所有应用程序类不太可能需要维护自己的属性列表。在任何情况下:

//Or abstract classes, depending on which makes more sense
interface IPropertyHaving
{
    List<IProperty> Properties { get; }
    void Add(Property property);
    //etc.
}

请注意,Properties属性是get-only,因为您不太可能希望接口的使用者能够完全替换属性列表。您的对象接口可以继承此属性,但定义特定于对象的功能。

interface IObject : IPropertyHaving 
{
    string ToXml();
    string ToJson();
    //Shared object properties
}

这些对象维护自己的数据/状态。他们知道如何序列化自己,并且他们有属性,但这都是。

您希望拥有一个“联系在一起”的界面或类别。您的应用程序功能 - 上下文的想法很好。

interface IDataContext : IPropertyHaving //?
{
    List<IObject> Objects { get; }
    void Save(IObject entity);
    IRelationshipManager RelationshipManager { get; }
    IObjectComparer ObjectComparer { get; }
    //Collection manipulation functions, etc.
}

现在,您的数据上下文仅负责维护您的IObject集合以及保存/检索/等。这使您的对象免于CRUD自己的责任。通过使用接口,您可以根据应用程序要求切换特定于案例的实现。请注意,您的上下文仅直接负责维护整个应用程序的状态 - 它具有您的对象集合,但它将大部分其他功能委托给单独的接口,这些接口组成了上下文。

同样,您可以定义一个IObjectComparer接口,该接口只有一个方法Compare(IObject first, IObject second)。然后,您的上下文可以包含IObjectComparer。这意味着虽然您的上下文能够比较对象,但您可以交换或修改 对象的比较方式,而不会影响任何其他代码。

您还可以拥有一个跟踪,创建或检索关系的IRelationshipManager类。同样,这可以在您的上下文中绑定在一起。然后,您的应用程序可以维护单个IContext,以及IDisplayManager或其他东西(这可能是您的GUI框架的一部分 - 这是WPF吗?),它知道如何将对象写入屏幕

有关您具体案例的更多详细信息,我们将能够提供更好的建议。