Enum atau Beberapa Kelas Terwaris

Sep 27 2020

Saya membaca tentang OOD dan menemukan masalah desain tempat parkir. Tempat parkir memiliki lantai parkir yang memiliki tempat parkir Kelas tempat parkir terlihat sebagai berikut:

public enum ParkingSpotType {
  HANDICAPPED, COMPACT, LARGE, MOTORBIKE, ELECTRIC
}
public abstract class ParkingSpot {
  private String number;
  private boolean free;
  private Vehicle vehicle;
  private final ParkingSpotType type;

  public boolean IsFree();

  public ParkingSpot(ParkingSpotType type) {
    this.type = type;
  }

  public boolean assignVehicle(Vehicle vehicle) {
    this.vehicle = vehicle;
    free = false;
  }

  public boolean removeVehicle() {
    this.vehicle = null;
    free = true;
  }
}

public class HandicappedSpot extends ParkingSpot {
  public HandicappedSpot() {
    super(ParkingSpotType.HANDICAPPED);
  }
}

public class CompactSpot extends ParkingSpot {
  public CompactSpot() {
    super(ParkingSpotType.COMPACT);
  }
}

public class LargeSpot extends ParkingSpot {
  public LargeSpot() {
    super(ParkingSpotType.LARGE);
  }
}

public class MotorbikeSpot extends ParkingSpot {
  public MotorbikeSpot() {
    super(ParkingSpotType.MOTORBIKE);
  }
}

public class ElectricSpot extends ParkingSpot {
  public ElectricSpot() {
    super(ParkingSpotType.ELECTRIC);
  }
}

Parameternya cukup jelas. Jadi di sini mengapa kita memerlukan kelas terpisah untuk setiap nilai ENUM? Apa keuntungan dari ini? Saya berpikir hanya memiliki satu jenis kelas ParkingSpot dengan satu bidang yang mewakili jenis slot parkir. Tapi mengapa kita perlu memiliki kelas terpisah untuk setiap nilai ENUM bersama dengan menyimpan Enum sebagai bidang juga?

Catatan: Untuk desain lengkap silakan lihat https://www.educative.io/courses/grokking-the-object-oriented-design-interview/gxM3gRxmr8Z

Jawaban

3 Flater Oct 27 2020 at 18:55

Anda benar bahwa saat ini kelas turunan tidak berguna, karena satu-satunya perbedaan mereka adalah satu nilai enum spesifik, yang diberi label dengan cara yang persis sama. Anda bisa menghilangkan enum atau class turunan, dan tidak ada yang akan berubah.

Namun, kesimpulan itu mungkin berubah ketika ada lebih banyak perbedaan daripada hanya nilai enum.

Misalnya, jika harga tempat parkir dihitung berbeda berdasarkan jenis tempat itu. Dengan memiliki kelas turunan, Anda dapat menyimpan logika penghitungan setiap jenis tempat parkir secara terpisah dan meminta mereka mengganti metode dasar yang sama.
Secara komparatif, jika Anda hanya memiliki kelas dasar untuk dikerjakan, itu harus berisi semua logika perhitungan.

Namun, contoh saat ini sedikit menyoroti konteks dan daftar fitur masa depan untuk memutuskan apakah warisan dijamin di sini atau tidak. Kami seharusnya tidak hanya mengevaluasi status kode saat ini (di mana pengamatan Anda benar), tetapi juga memperhitungkan setiap perubahan yang direncanakan / diharapkan dalam waktu dekat.


Yang sedang berkata, saya curiga bahwa Anda umumnya akan berakhir baik harus menghapus kelas turunan atau enum. Saya tidak melihat manfaat menerapkan informasi yang sama dalam dua cara berbeda.

Ewan Sep 27 2020 at 16:50

Perbedaannya menjadi jelas jika kita pertimbangkan

CompactSpot.Assign(Car.SUV)

ini jelas harus menghasilkan kesalahan dari beberapa jenis dan kami memiliki dua pilihan tentang bagaimana menerapkannya.

antara:

ParkingSpot.Assign(car)
{
    if(car is SUV && this.type = COMPACT)
    {
        throw CarTooLarge()
    }
    if(car != HANDICAPPED && this.type == HANDICAPPED)
    ....
}

CompactSpot : ParkingSpot
    Assign(car)
    {
        if(car is SUV)
        {
            throw CarTooLarge()
        }
        base.assign(car);
    }
}

Pendekatan Warisan memungkinkan kita untuk membagi logika kondisional antara beberapa kelas daripada memiliki blok dan logika bersyarat yang besar di kelas dasar.

Jika saya menggunakan kelas ParkingSpot Anda sebagai dll biner, saya dapat mewarisi jenis ParkingSpot baru dan menambahkan logika saya sendiri. Yang tidak dapat saya lakukan jika Anda memiliki enum

radarbob Oct 29 2020 at 09:20

Pertanyaan itu terjawab dengan sendirinya jika kita berpikir tentang perilaku daripada negara, dan kita harus melakukannya. Pewarisan dimotivasi oleh "melakukan hal yang sama, tetapi berbeda" atau memiliki fungsi tambahan untuk berbagai subtipe. Mungkin para desainer memiliki gagasan yang baik bahwa ParkingSpotdan Vehicleperilaku akan berkembang dan berkembang. Mungkin demi pembelajaran mereka hanya membuat sub-pengetikan.

Meskipun ENUM akan membedakan kendaraan / tempat parkir dengan tipe yang sama, persyaratan untuk fungsionalitas harus menjadi pertimbangan utama. Meski begitu, enum mungkin masih sesuai.

Ada kebutuhan untuk mencocokkan kendaraan dan tempat parkir - bahwa ENUM hanyalah detail implementasi. Jadi VehicleTypeproperti kemaluan sepertinya cocok. Properti ini lebih dalam semangat OO daripada, katakanlah, kode klien yang mengobrak-abrik Refleksi / metadata. Kode klien tidak boleh menghitung status objek lain.


Tetapi harus ada beberapa layanan, katakanlah ParkingAllocator yang pertama-tama akan mencari slot gratis yang relevan untuk kendaraan tertentu dan hanya jika slot gratis dari kendaraan tertentu tersedia, kami akan memarkir kendaraan di sana. Jadi jika kami mencoba untuk menetapkan kendaraan ke suatu tempat, kami sangat yakin bahwa tempat tersebut cukup besar untuk kendaraan. Apakah ini masuk akal?

Diagram use case menunjukkan petugas parkir dan pelaku pelanggan. Mereka tidak ada di diagram kelas tetapi mereka adalah bagian dari ruang masalah.


Saya pikir ada persyaratan yang hilang atau rusak.

  • Apakah kendaraan yang lebih kecil diperbolehkan dalam slot yang lebih besar? Sepeda motor muat kemana-mana.

  • Objek kendaraan tertentu dapat berupa listrik atau memiliki izin penyandang cacat atau keduanya - dalam kehidupan nyata - jadi saya melihat ElectricSlot& HandicapSlotsebagai atribut tempat parkir. Seperti yang ditunjukkan, diagram kelas di sini tidak konsisten dengan konsep kendaraan dengan ukuran berbeda yang dipasang di slot ukuran berbeda.

  • Tidak ada kecocokan yang jelas antara jenis tempat parkir dan jenis kendaraan. Kendaraan mana yang membutuhkan "besar", misalnya? Begitu saja, Kamus secara eksplisit dapat mencocokkan tempat dengan kendaraan, dan / atau sebaliknya. Juga nilai integer enum yang mendasari dapat mewakili ukuran relatif tempat parkir. Dan seperti yang saya katakan di atas, "listrik" bukanlah ukuran.


Struktur data!

barang ini ...

if(car is SUV)
    {
        throw CarTooLarge()
    }
    base.assign(car);
}

hilang jika pencocokan jenis kendaraan / jenis tempat ini adalah struktur data. A Dictionaryadalah struktur data. Begitu saja, saya melihat dua kamus - kendaraan-> tempat dan tempat-> kendaraan - sebagai inti dari kelas dengan metode yang sesuai.