質問

I have just started a project to make my employer a management software. I have a niggling, but potentially simple, query that I can't seem to find any information on.

Is it prudent/good practice to have a 2 way 'has a' relationship between objects. So can, for example, a Client object 'have a' Site, and then the Site 'has a' Client, where the Client object is the Client that 'has' the Site?

public class Client {
    Site site;
}

public class Site {
    Client client;
}

Is there anything objectionable (no pun intended) to this, or is it fine? I am currently creating a mock-up UML for the project, and this has been bothering me.

役に立ちましたか?

解決

Is there anything objectionable to this, or is it fine?

There's no definitive answer to this. The best answer is: it depends to the design of your application.

When to use it

If your Client object should navigate to the Site object and your Site object should navigate to the Client object, then the current example in your code is fine. Still, probably you will need some way to associate these elements, probably by an additional id field on one of the classes or in both.

If it happens that you work with a framework that helps you to bind the classes automatically like Hibernate, then maintaining the circular reference won't be a problem for you.

When not to use it

Basically, for text serialization, since it will generate an infinite loop. As already mentioned in Raibaz's answer, a library like Jackson will fall into infinite loop while serializing Client or Site class into a JSON string1. Note that this is also valid when serializing to other String data like passing the objects through a JAX-WS web service in XML (more info: What happens to generic class in jax-ws webservice?).

1 This can be solved using annotations (@Something) that belong to a specific library e.g. @JsonManagedReference and @JsonBackReference from Jackson library, as noted by @SimonAndréForsberg, but the downside of this solution is that your classes will have tight coupling with the library.

他のヒント

It is common, but I would consider how loosely coupled you want the child object to be from its parent. If you have the reference to the parent from the child object then you will not be able to reuse the object with another parent / no parent.

It's common to have a mutual association between objects.

For example, in some user interface toolkits, a visual component will have references to its children, and each child may have a reference to its parent.

The term has-a is frequently used to communicate ownership of one object by another. When this is true, the relationship is usually one-way.

One good definition of these terms is provided in "The Unified Modeling Language User Guide", by Booch, Rumbaugh and Jacobson:

Aggregation -- A plain association between two classes represents a structual relationship between peers, meaning that both classes are conceptually at the same level, no one more important than the other. Sometimes, you will want to model a "whole/part" relationship, in which one class represents a larger thing (the "whole"), which consists of smaller things (the "parts"). This kind of relationship is called aggregation, which represents a "has-a" relationship, meaning that an object of the whole has objects of the part.

It's quite normal and quite common to have a bidirectional association like the one in your example.

The only caveat you may want to consider is when you are going to serialize your objects, for instance in json using Jackson or any other library, you should exclude one of the two sides of the association from serializing to avoid ending in an infinite loop.

I'd try to stick to 1-way relationship whenever possible. 2-way relationships makes two classes tied together and a change in one of them causes the other to change two. Ask yourself if such relation is really natural...

If you have to, just make sure both are interfaces or at least one of them is.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top