11

I have two objects that represent a 'Bar/Club' ( a place where you drink/socialise).

In one scenario I need the bar name, address, distance, slogon

In another scenario I need the bar name, address, website url, logo

So I've got two objects representing the same thing but with different fields.

I like to use immutable objects, so all the fields are set from the constructor.

One option is to have two constructors and null the other fields i.e:

class Bar {
     private final String name;
     private final Distance distance;
     private final Url url;

     public Bar(String name, Distance distance){
          this.name = name;
          this.distance = distance;
          this.url = null;
     }

     public Bar(String name, Url url){
          this.name = name;
          this.distance = null;
          this.url = url;
     }

     // getters
}

I don't like this as you would have to null check when you use the getters

In my real example the first scenario has 3 fields and the second scenario has about 10, so it would be a real pain having two constructors, the amount of fields I would have to declare null and then when the object are in use you wouldn't know which Bar you where using and so what fields would be null and what wouldn't.

What other options do I have?

Two classes called BarPreview and Bar?

Some type of inheritance / interface?

Something else that is awesome?

6
  • 29
    Wow, you've actually come up with a legitimate use of Bar as an identifier! Commented Jul 5, 2012 at 21:32
  • 1
    if you are sharing some properties, one option would be to implement a base class.
    – Yusubov
    Commented Jul 5, 2012 at 21:41
  • 1
    I never thought of that. Writing any kind of code for my Bar/Foo dog parlor could get really confusing. Commented Jul 6, 2012 at 2:04
  • 1
    Let’s Play The Guessing Game
    – gnat
    Commented Jul 6, 2012 at 7:12
  • 4
    @gnat How are people guessing. From your link quote: You should only ask practical, answerable questions based on actual problems that you face. and that's exactly what's happening here
    – Blundell
    Commented Jul 6, 2012 at 7:14

9 Answers 9

9

My thoughts:

A "Bar", as represented in your domain, has all of the things that may be needed in either place: name, address, URL, logo, slogan, and "distance" (I'm guessing from the requester's location). Therefore, in your domain, there should be one "Bar" class that is the authoritative source of data for one bar, no matter where the data will be used later. This class should be mutable, so that changes to the bar's data can be made and saved when necessary.

However, you have two places in which this Bar object's data is needed, and both of them only need a subset (and you don't want that data to be changed). The usual answer is a "data transfer object" or DTO; a POJO (plain ol' Java object) containing the immutable property getters. These DTOs can be produced by calling a method on the main Bar domain object: "toScenario1DTO()" and "toScenario2DTO()"; the results being a hydrated DTO (meaning that you only need to use the long, complicated constructor in one place).

If you ever needed to send data back to the main domain class (to update it; what's the point of data if you can't change it as needed to reflect the current state of the real world?), you could construct one of the DTOs, or use a new mutable DTO, and hand it back to the Bar class using an "updateFromDto()" method.

EDIT: to provide an example:

public class Bar {
     private String name;
     private Address address; 
     private Distance distance;
     private Url url;
     private Image logo;
     private string Slogan;

     public OnlineBarDto ToOnlineDto()
     {
         return new OnlineBarDto(name, address, url, logo);
     }

     public PhysicalBarDto ToPhysicalDto()
     {
         return new PhysicalBarDto(name, address, distance, slogan);
     }

     public void UpdateFromDto(PhysicalBarDto dto)
     {
         //validation logic here, or mixed into assignments

         name = dto.Name;
         address = dto.Address;
         distance = dto.Distance;
         slogan = dto.Slogan;
     }

     public void UpdateFromDto(OnlineBarDto dto)
     {
         //Validate DTO fields before performing assignments

         name = dto.Name;
         address = dto.Address;
         url= dto.Url;
         logo = dto.Logo;
     }

     // getters/setters - As necessary within the model and data access layers;
     // other classes can update the model using DTOs, forcing validation.
}

public class PhysicalBarDto
{
     public final String Name;
     public final Address Address;
     public final Distance Distance;
     public final String Slogan;

     public PhysicalBarDto(string Name, Address address, Distance distance, string slogan) 
     { //set instance fields using parameter fields; you know the drill }
}

public class OnlineBarDto
{
     public final String Name;
     public final Address Address;
     public final Image Logo;
     public final Url Url;

     public OnlineBarDto(string Name, Address address, Url url, Image logo) 
     { //ditto }
}

The Address, Distance and Url classes should either be immutable themselves, or when used in the DTOs they should be replaced with immutable counterparts.

7
  • what does the acronym DTO stand for? I don't quite get what your saying could you put it into a worked example please. fyi The data comes from a server so once either form of this class is 'hydrated' the fields won't need to be changed, just used to display on the UI
    – Blundell
    Commented Jul 5, 2012 at 22:49
  • 1
    DTO stands for "data transfer object", and refers to a data class of very simple structure used to move data from the "rich" domain layer out to upper layers like the UI, without exposing the actual domain layer to the UI (allowing changes to be made to the domain without affecting the UI as long as the DTO doesn't have to change).
    – KeithS
    Commented Jul 5, 2012 at 23:25
  • mutability has no bearing what so ever on modification or persistance.
    – user7519
    Commented Jul 6, 2012 at 2:28
  • 4
    @JarrodRoberson - are you kidding? If a class is immutable (can't be changed in-place after instantiation) the only way to make a change to the data in the data layer is to construct a new instance representing the same record (same PK) with different members. While "mutating" methods that produce a new instance can make it easier, it still has a huge bearing on modification and persistence.
    – KeithS
    Commented Jul 6, 2012 at 3:00
  • 1
    @JarrodRoberson Listen to the community. You are wrong.. In fact half the comments in this whole answer show that we need some basic OO schooling around the board -- it's disgusting.. Commented Jul 6, 2012 at 17:43
5

If you care about only a subset of the properties, and you want to make sure they don't get mixed up, create two interfaces, and use that to talk to your base object.

1
  • 1
    You say that but could you give an example using the Bar class
    – Blundell
    Commented Jul 6, 2012 at 6:56
3

The Builder Pattern (or something close to it) might be of use here.

Having immutable objects is an admirable thing, but the reality is that with Reflection in Java, nothing is truly safe ;-).

2
  • I can see how the HawaiianPizzaBuilder works because the values it needs are hardcoded. However how can you use this pattern if the values are retrieved and passed to a constructor? The HawaiianPizzaBuilder would still have all the getters that the SpicyPizzaBuilder has so null is possible. Unless you combine this with @Jarrods Null Object Pattern. A code example with Bar would get your point across
    – Blundell
    Commented Jul 5, 2012 at 23:12
  • +1 I use builder in cases like this, works like a charm - including, but not limited to setting reasonable defaults instead of null when I want this
    – gnat
    Commented Jul 6, 2012 at 7:14
3

The key point here is the difference between what a "Bar" is and how you use it in one or another context.

The Bar is a single entity in the real world (or an artificial world, like a game), and only ONE object instance should represent it. Anytime later, when you don't create that instance from a code segment, but load it from a config file or a database, this will be more evident.

(To be even more esoteric: each Bar instance has a different lifecycle than the object that represents it when your program runs. Even if you have a source code that creates that instance, it means that the Bar entity as it is described, "exists" in a dormant state in your source code, and "awaken" when that code actually creates it in the memory...)

Sorry for the long start, but I hope this makes my point clear. You have ONE Bar class having all the attributes that you would ever need, and one Bar instance representing each Bar entity. This is correct in your code, and independent from how you want to see the same instance in different contexts.

The latter can be represented by two different interfaces, that contain the required access methods (getName(), getURL(), getDistance()), and the Bar class should implement both. (And perhaps the "distance" will change to "location", and the getDistance() becomes a calculation from another location :-) )

But the creation is for the Bar entity and not for the way you want to use that entity: one constructor, all fields.

EDITED: I can write code! :-)

public interface Place {
  String getName();
  Address getAddress();
}

public interface WebPlace extends Place {
   URL getUrl();
   Image getLogo();
}

public interface PhysicalPlace extends Place {
  Double getDistance();
  Slogon getSlogon();
}

public class Bar implements WebPlace, PhysicalPlace {
  private final String name;
  private final Address address;
  private final URL url;
  private final Image logo;
  private final Double distance;
  private final Slogon slogon;

  public Bar(String name, Address address, URL url, Image logo, Double distance, Slogon slogon) {
    this.name = name;
    this.address = address;
    this.url = url;
    this.logo = logo;
    this.distance = distance;
    this.slogon = slogon;
  }

  public String getName() { return name; }
  public Address getAddress() { return address; }
  public Double getDistance() { return distance; }
  public Slogon getSlogon() { return slogon; }
  public URL getUrl() { return url; }
  public Image getLogo() { return logo; } 
}
1

Appropriate Pattern

What you are looking for is most commonly referred to as the Null Object Pattern. If you don't like the name you can call it the Undefined Value Pattern, same semantics different label. Sometimes this pattern is called Poison Pill Pattern.

In all these cases, the Object is a replacement or stand in for a Default Value instead of null. It doesn't replace the semantic ofnullbut makes it easier to work with the data model in a more predictable way becausenull` should now never be a valid state.

It is a Pattern where you reserve a special instance of a given class to represent an otherwise null option as a Default Value. This way you don't have to check against null, you can check identity against your known NullObject instance. You can safely call methods on it and the like without worrying about NullPointerExceptions.

This way you replace your null assignments with their representative NullObject instances and you are done.

Proper Object Oriented Analysis

This way you can have a common Interface for polymorphism and still have protection from having to worry about the absence of data in the specific implementations of the interface. So some Bar may not have web presence, and some might not have location data at the time of construction. Null Object Patter lets you provide a default value for each of these that is a marker for that data that says the same thing, nothing has been supplied here, without having the deal with checking for NullPointerException all over the place.

Proper Object Oriented Design

First have an abstract implementation that is a super set of all the attributes that both Bar and Club share.

class abstract Establishment 
{
     private final String name;
     private final Distance distance;
     private final Url url;

     public Bar(final String name, final Distance distance, final Url url)
     {
          this.name = name;
          this.distance = distance;
          this.url = url;
     }

     public Bar(final String name, final Distance distance)
     {
          this(name, distance, Url.UNKOWN_VALUE);
     }

     public Bar(final String name, final Url url)
     {
          this(name, Distance.UNKNOWN_VALUE, url);
     }

     // other code
}

Then you can implement sub classes of this Establishment class and add just the specific things you need for each of the Bar and Club classes that doesn't apply to the other.

Persistence

These placeholder objects if constructed correctly can be transparently stored in a database without any special handling as well.

Future Proof

If you decided to jump on the Inversion of Control / Dependency Injection bandwagon later one, this pattern makes that easy to inject these marker objects as well.

0
0

I think the problem is that you aren't modeling a Bar in either of those scenarios (And your are modeling two different problems, objects, etc..). If I see a class Bar I'd expect some functionality related to drinks, the menus, the seats available, and your object has none of that. If I see your objects behavior you are modeling information about an establishment. Bar is what you are using those for at this moment, but it's not the intrinsically behavior they are implementing. (In another context: If you are modeling a Marriage, you'll have two instance variables Person wife; Person husband; a wife is the current role you are giving that object at that moment, but the object is still a Person). I'd do something like this:

class EstablishmentInformation {
     private final String name;

     public EstablishmentInformation(String name){
          this.name = name;
     }

     // getters
}

class EstablishmentLocationInformation {
    EstablishmentInformation establishmentInformation;
     private final Distance distance;

     public EstablishmentLocationInformation (String name, Distance distance){
          this.establishmentInformation = new EstablishmentInformation(name)
          this.distance = distance;
     }
}

class EstablishmentWebSiteInformation {
    EstablishmentInformation establishmentInformation;
     private final Url url;

     public EstablishmentWebSiteInformation(String name, Url url){
          this.establishmentInformation = new EstablishmentInformation(name)
          this.url = url;
     }
}
-1

There's really no need to overcomplicate this. You need two different kinds of object? Make two classes.

class OnlineBar {
     private final String name;
     private final Url url;
     public OnlineBar(String name, Url url){
          this.name = name;
          this.url = url;
     }

     // ...
}
class PhysicalBar {
     private final String name;
     private final Distance distance;
     public PhysicalBar(String name, Distance distance){
          this.name = name;
          this.distance = distance;
     }
     //...
}

If you need to operate on them equally, consider adding an interface, or using reflection.

5
  • @David: Oh noes. They have like, one whole data member in common. EMERGENCY!
    – DeadMG
    Commented Jul 6, 2012 at 0:20
  • without some common interface there is no polymorphism in this solution, neither of these classes could be substituted for the other with this poor design decision. It isn't that they don't have the same superset of attributes, it is that by default some of those attributes are null. Remember null means the absence of data, not the absence of the attribute.
    – user7519
    Commented Jul 6, 2012 at 1:57
  • 1
    @DeadMG This is quite possibly an exercise in exactly the idea of grouping shared values into parent objects.. your solution would not get full credit if you proposed it in that context. Commented Jul 6, 2012 at 1:58
  • The OP does not specify any need for substitutability. And as I said, you can just add an interface or use reflection if you want to.
    – DeadMG
    Commented Jul 6, 2012 at 8:41
  • @DeadMG But reflection is like trying to write a cross platform mobile app using one environment -- It may work, but it's not correct. The penalty for calling a method using reflection is anywhere between 2 and 50 times slower than a normal method call. Reflection is not a cure-all.. Commented Jul 9, 2012 at 9:22
-1

My answer to anyone with this type of problem is to break it down into manageable steps.

  1. First just create two classes BarOne and BarTwo (or call them both Bar but in different packages)
  2. Start using your objects as separate classes don't worry about the code duplication for now. You will notice when you get cross over (duplicate methods) from one to the other
  3. You may find out that they are in no way related, and so you should ask yourself are they both really a bar if not rename the offending class to what it now represents
  4. If your finding common fields or behaviour you can then extract an interface or superclass with the common behaviour
  5. Once you have an interface or superclass you could create a builder or factory to create/retrieve your implementation objects

(4 and 5 are what the the other answers to this question are about)

-2

You need a base class, for example, Location which has a name and an address. Now, you have two classes Bar and BarPreview extend the base class Location. In each class you initialize the super class common variables and then your unique variables:

public class Location {
    protected final String name;
    protected final String address:

    public Location (String locName, String locAddress) {
    name = locName;
    address = locAddress
    }

}

public class Bar extends Location {
    private final int dist;
    private final String slogan;

    public Bar(String barName, String barAddress,
               int distance, String barSlogan) {
    super(locName, locAddress);
    dist = distance;
    slogan = barSlogan;
    }
}

And similar for the BarPreview class..

If it makes you sleep better at night, replace all instances of Location in my code with AnythingYouThinkWouldBeAnAppropriateNameForAThingThatABarExtendsSuchAsFoodServicePlace -- ffs.

11
  • the OP wants the instance to be immutable, that means everything has to be final.
    – user7519
    Commented Jul 5, 2012 at 22:51
  • 1
    This could work, you need to final the fields @David. Bar shouldn't extend Location though that doesn't make sense. Perhaps Bar extends BaseBar and BarPreview extends BaseBar these names don't really sound too good either though, I was hoping for something more elegant
    – Blundell
    Commented Jul 5, 2012 at 23:23
  • @JarrodRoberson I'm just sketching it for him.. just add final for it to be immutable. It's a no-brainer.. The fundamental problem with the OP's question is that he doesn't know how to have a base class and two separate classes that extend a base class. I'm simply detailing that. Commented Jul 5, 2012 at 23:45
  • @Blundell what in the world are you talking about? A Bar is a Location. Just replace my Location with your BaseBar and it's the exact same thing.. You do know that when one class extends another the class it extends doesn't have to be named Base[ClassThatWillExtend] right? Commented Jul 5, 2012 at 23:46
  • 1
    @DavidCowden, can you stop to advertise your answer as a comment below every other answer, please?
    – marktani
    Commented Jul 9, 2012 at 10:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.