2

I'm making an Airplane seat reserve program, and I'm working on two of the classes: Passenger and Seat. I want to have the Seat hold a Passenger object and vice versa because in the program I want to be able to print a list of seats with their passenger or, if there is no passenger, OPEN, as well as a list of passengers with their corresponding seat.

When I insert a passenger into a Seat, should I also insert the seat into the Passenger in the same insertPassenger method or should I simply call both methods separately, following the idea that a set method should only do one thing? Also, is this Passenger-has-a-Seat and Seat-has-a-Passenger mindset appropriate for my needs or is there a better, more efficient way with less coupling?

public class Seat {
    private Passenger passenger;
    //more fields and constructor etc.
    public void insertPassenger(Passenger passenger) {
        this.passenger = passenger;
        passenger.setSeat(this); //is this line good or terrible?
    }
}

public class Passenger {
    //String names and stuff
    private Seat seat;
    //Seat is left uninitialized in constructor, is this a good idea?
    public Passenger(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
    public void setSeat(Seat seat) {
        this.seat = seat;
    }
}
DurianHLN
  • 71
  • 4

5 Answers5

0

A simple solution without using the collections package,

class Passenger {

  private Seat seat;

  void setSeat (Seat s){
     this.seat = s;
  }

  assignSeat (Seat s){
     s.setPassenger(this)
     setSeat(s);
   }

}

That meets your criteria of having the setter do only one thing. But just for the record, it is often necessary for setters to do more than one thing in order to maintain the invariants of your class.

But what you really want to do is establish a relationship between Passengers and Seats. That is called a mapping. Maps are available in the collections package. It requires an understanding of Generics which is beyond the scope of this answer.

new HashMap<Passenger, Seat>  seatMap = new HashMap<>();


class Passenger {

    assignSeat(Seat seat){
       seatMap.put(this, seat);
    }
}

now when you want to list all passengers and their seats you can use code like

 for(Passenger p : seatMap.getKeys()){
     System.println("Passenger " + p + " is in seat " seatMap.getValue(p));
  }

I haven't actually compiled all this code. But I think it gives you the gist of what is meant by a mapping. This is a one way mapping. That means if you know the passenger you can directly find their seat. If you know the seat, you can not directly find the passenger. You must search all of the passengers in the map to find the one passenger that has the seat. What's worse, in the code above, nothing prevents you from putting to passengers in the same seat (except by checking every passenger to make sure the seat is not already taken by someone else). But all of these drawbacks were true of my first solution.

What you really need is a 2 way map. Maybe Java has one of those in the collections package. :)

Teto
  • 475
  • 2
  • 10
  • 2 way maps don't exist in Java but this answer points to some that easily available. http://stackoverflow.com/questions/9783020/bidirectional-map – Teto Nov 05 '16 at 03:19
0

If it were me, I wouldn't have the seat be an object. I would use a hash map to hold the passenger. Something like HashMap<String, Passenger> seats = new HashMap<String, Passenger>(); then you could assign seats like:

Passenger person = Passenger("John", "Doe"); 
Passenger person2 = Passenger("Jane", "Doe"); 
seats.add("1A", person1);
seats.add("1B", person2); 

and so on. You could then get the value for the seat by using the key (seat) or the value (passenger).

The problem with using the seat object, is that you don't have a clear value for the seat, and you could also have duplicate values. It would be hard to tell if seat 1A is taken or not. By having a HashMap you can guarantee that each value is unique, as you can only have 1 key. Rather than having a Seat class, I would make a Flight class. Seats don't really have much use in OOP. A seat is just where someone sits. It's more organizational. Everything that you do with a flight is Passenger based rather than seat based.

But this is just one of many ways you could do this.

BlackHatSamurai
  • 23,275
  • 22
  • 95
  • 156
0

I am not totally sure this is going to work for you but if I do, I would be doing like this:

class Flight{
    Set<SeatPassangerMapping> seatPassangerMapping;
}

class SeatPassengerMapping{
    Seat seat;
    Passenger passenger;

    Flight flight;

    public boolean equals(Object obj){
        if(obj instance of SeatPassangerMapping){
            // right your logic here on the basis of flight
        }

        return false
    }

}

Its because, a passenger will have different sheets in different flights.

Deepak Agrawal
  • 1,301
  • 5
  • 19
  • 43
0

The term you're looking for is circular dependency, or even circular reference. See this answer for another perspective.

Two maps would work well. These would be owned by whatever is containing the people and seats (e.g. a Flight class, whatever). This would act as a bidirectional map (which is also available in third party libraries as an actual collection type), giving you full coverage of each list of elements and whatever they map to (if anything).

Since you likely already have some source of data that determines what these linkages are, you could apply that to these maps instead.

// Linked in case you want to preserve insertion order
Map<Seat, Passenger> seatMap = new LinkedHashMap<>();
Map<Passenger, Seat> passengerMap = new LinkedHashMap<>();

//
// Populate the maps here.
//   
//   if a seat has no passenger: 
//   seatMap.put(seat, null);
//

void printSeats() {
    for (Map.Entry<Seat, Passenger> entry : seatMap.entrySet()) {
        Passenger passenger = entry.getKey();
        Seat seat = entry.getValue();
        // print the seat 
    }
}

void printPassengers() {
    for (Map.Entry<Passenger, Seat> entry : passengerMap.entrySet()) {
        Seat seat = entry.getKey();
        Passenger passenger = entry.getValue();
        // print the passenger
    }
}
Community
  • 1
  • 1
drhr
  • 2,261
  • 2
  • 17
  • 35
0

I see this thing different (just to complement other answers):

You have a flight with seats and passengers, so what i'd do is implement the flight class to add seat-passenger logic. The only trick thing is you have to choose which Passenger will be the non-seated:

  1. (seatNumber, null)
  2. (seatNumber, defaultPassenger with id=0, and name=OPEN)

I took the option two:

Passenger:

   public class Seat {
        private int seatNumber;

        public Seat ( )
        {

        }

        public Seat ( int seatNumber )
        {
            this.seatNumber = seatNumber;
        }
        /**
         * @return the seatNumber
         */
        public int getSeatNumber ( )
        {
            return seatNumber;
        }

        /**
         * @param seatNumber the seatNumber to set
         */
        public void setSeatNumber ( int seatNumber )
        {
            this.seatNumber = seatNumber;
        }

        @Override
        public String toString ( )
        {
            return "Seats [seatNumber=" + seatNumber + "]";
        }

        /* (non-Javadoc)
         * @see java.lang.Object#hashCode()
         */
        @Override
        public int hashCode ( )
        {
            final int prime = 31;
            int result = 1;
            result = prime * result + seatNumber;
            return result;
        }

        /* (non-Javadoc)
         * @see java.lang.Object#equals(java.lang.Object)
         */
        @Override
        public boolean equals ( Object obj )
        {
            if ( this == obj )
                return true;
            if ( obj == null )
                return false;
            if ( getClass ( ) != obj.getClass ( ) )
                return false;
            Seat other = ( Seat ) obj;
            if ( seatNumber != other.seatNumber )
                return false;
            return true;
        }



    }

Seat:

public class Seat {
    private int seatNumber;

    public Seat ( )
    {

    }

    public Seat ( int seatNumber )
    {
        this.seatNumber = seatNumber;
    }
    /**
     * @return the seatNumber
     */
    public int getSeatNumber ( )
    {
        return seatNumber;
    }

    /**
     * @param seatNumber the seatNumber to set
     */
    public void setSeatNumber ( int seatNumber )
    {
        this.seatNumber = seatNumber;
    }

    @Override
    public String toString ( )
    {
        return "Seats [seatNumber=" + seatNumber + "]";
    }

    /* (non-Javadoc)
     * @see java.lang.Object#hashCode()
     */
    @Override
    public int hashCode ( )
    {
        final int prime = 31;
        int result = 1;
        result = prime * result + seatNumber;
        return result;
    }

    /* (non-Javadoc)
     * @see java.lang.Object#equals(java.lang.Object)
     */
    @Override
    public boolean equals ( Object obj )
    {
        if ( this == obj )
            return true;
        if ( obj == null )
            return false;
        if ( getClass ( ) != obj.getClass ( ) )
            return false;
        Seat other = ( Seat ) obj;
        if ( seatNumber != other.seatNumber )
            return false;
        return true;
    }



}

Flight:

import java.util.HashMap;

public class Flight
{
    private HashMap<Seat, Passenger>  seatMap;


    public Flight(int numberOfSeats)
    {
        seatMap = new HashMap<>();

        for(int i = 1; i <= numberOfSeats; i++)
        {
            seatMap.put ( new Seat ( i ) , new Passenger ( ) );
        }
    }

    /**
     * @return the seatMap
     */
    public HashMap < Seat , Passenger > getSeatMap ( )
    {
        return seatMap;
    }


    /**
     * @param seatMap the seatMap to set
     */
    public void setSeatMap ( HashMap < Seat , Passenger > seatMap )
    {
        this.seatMap = seatMap;
    }

    public void sitPassenger (int seatNumber, Passenger passenger)
    {
        seatMap.put ( new Seat ( seatNumber ) , passenger );
    }

    @Override
    public String toString ( )
    {
        return "Flight [seatMap=" + seatMap + "]";
    }

}

MainClass:

public class mainProgram
{
    public static void main(String args [])
    {
        //set number of seats
        Flight myFlight = new Flight ( 3 );
        //first passenger
        Passenger firstP = new Passenger ( );
        firstP.setSocialNumber ( 19993 );
        firstP.setName ( "John" );
        //second passenger
        Passenger secondP = new Passenger ( );
        secondP.setSocialNumber ( 19994 );
        secondP.setName ( "Brian" );
        //sit them
        myFlight.sitPassenger ( 1 , firstP );
        myFlight.sitPassenger ( 2 , secondP );
        //output
        System.out.println ( myFlight.toString ( ) );
    }
}

Output:

Flight [seatMap={

Seats [seatNumber=1]=Passenger [socialNumber=19993, name=John],

Seats [seatNumber=2]=Passenger [socialNumber=19994, name=Brian],

Seats [seatNumber=3]=Passenger [socialNumber=0, name=OPEN]

}]

This solution allow to have the same passenger on different flights (seats) which an Airplane seat reserve program should do, IMHO.

Rcordoval
  • 1,932
  • 2
  • 19
  • 25