Semua Artikel
Diposting pada 10 Desember 2024

Arsip Tugas 3 - Pemrograman Berbasis Desktop - Universitas Terbuka - 2024

By Khafid Ilham
Penulis

Tugas 3 Pemrograman Berbasis Desktop - Sistem Pemesanan Restoran

Oleh: Khafid Ilham

#TetaplahBerbeda

Catatan Penting: Artikel ini adalah penjelasan dari arsip Tugas 3 yang sudah selesai dikerjakan. Tujuan saya membagikan ini adalah untuk membantu teman-teman yang mungkin masih kesulitan memahami konsep pemrograman desktop, khususnya implementasi sistem restoran sederhana menggunakan Java. Mari kita belajar bersama! 😊

Pendahuluan

Hai teman-teman! Hari ini saya akan berbagi pengalaman dalam mengembangkan aplikasi manajemen restoran sederhana menggunakan Java. Aplikasi ini merupakan bagian dari Tugas 3 mata kuliah Pemrograman Berbasis Desktop di Universitas Terbuka.

Penjelasan terkait konsep-konsep tugas:

  1. Abstraksi dan Inheritance:

    • Abstraksi diterapkan dengan membuat kelas abstrak MenuItem yang memiliki metode abstrak tampilMenu(). Kelas ini menjadi dasar bagi kelas-kelas turunan seperti Makanan, Minuman, dan Diskon.
    • Inheritance digunakan dengan kelas Makanan, Minuman, dan Diskon yang merupakan subclass dari MenuItem. Kelas-kelas ini mewarisi atribut dan metode dari MenuItem dan mengimplementasikan metode tampilMenu() untuk menampilkan informasi yang lebih spesifik.
  2. Encapsulation:

    • Atribut-atribut dalam kelas seperti nama, harga, dan kategori di MenuItem, serta atribut-atribut lainnya seperti jenisMakanan, jenisMinuman, dan diskon, bersifat private dan hanya dapat diakses melalui metode getter (misalnya getNama(), getHarga(), dll). Ini adalah penerapan prinsip encapsulation.
  3. Polymorphism:

    • Polymorphism terjadi saat metode tampilMenu() dipanggil pada objek MenuItem. Setiap objek turunan seperti Makanan, Minuman, dan Diskon memiliki implementasi tampilMenu() yang berbeda. Meskipun menggunakan tipe data MenuItem, hasil yang ditampilkan tergantung pada jenis objek yang sebenarnya (polymorphism).
  4. Exception:

    • Pengecualian digunakan dalam kelas Menu saat mencari menu yang tidak ada dengan metode cariMenu(). Jika item tidak ditemukan, maka akan dilemparkan exception yang menangani kasus tersebut.
    • Juga digunakan saat memuat atau menyimpan file, jika ada kesalahan dalam I/O, pengecualian akan ditangani dengan pesan error.
  5. I/O dan Operasi File:

    • Operasi I/O digunakan untuk menyimpan dan memuat menu serta struk pesanan ke dan dari file dengan menggunakan BufferedWriter dan BufferedReader.
    • Program memungkinkan untuk memuat file menu dari disk, menyimpan perubahan ke file, serta menyimpan dan memuat struk pesanan pelanggan.
  6. Struktur Keputusan dan Pengulangan:

    • Struktur keputusan digunakan di banyak tempat, seperti dalam pemilihan jenis menu pada menu utama (switch), serta dalam memeriksa kategori item menu pada saat menyimpan dan memuat file.
    • Struktur pengulangan (looping) digunakan di berbagai tempat, seperti dalam iterasi ArrayList daftarMenu dan daftarPesanan untuk menampilkan daftar menu atau pesanan.
  7. Array dan String:

    • Array digunakan untuk menyimpan item menu dan pesanan dalam bentuk ArrayList<MenuItem>.
    • String digunakan untuk menyimpan dan memanipulasi data, seperti nama menu, jenis menu, dan dalam operasi I/O (membaca dan menulis file).

- Full Code :

import java.io.*;
import java.util.ArrayList;
import java.util.Scanner;

// 1.	Buatlah sebuah kelas abstrak MenuItem yang akan menjadi kelas dasar
// untuk semua menu item dalam restoran. Kelas ini harus memiliki atribut nama
// (String), harga (double), dan kategori (String). Definisikan metode abstrak
// tampilMenu() yang akan digunakan untuk menampilkan informasi tentang item menu.
abstract class MenuItem {
    private String nama;
    private double harga;
    private String kategori;

    public MenuItem(String nama, double harga, String kategori) {
        this.nama = nama;
        this.harga = harga;
        this.kategori = kategori;
    }

    public String getNama() {
        return nama;
    }

    public double getHarga() {
        return harga;
    }

    public String getKategori() {
        return kategori;
    }

    // Kelas abstrak adalah kelas yang tidak dapat langsung diinstansiasi atau dibuat objeknya.
    // Kelas ini dirancang untuk menjadi kelas dasar atau superclass yang akan diwarisi
    // oleh kelas-kelas lainnya.
    public abstract void tampilMenu();

    // Kelas biasa adalah kelas yang dapat langsung diinstansiasi,
    // artinya Anda bisa membuat objek dari kelas ini secara langsung.
    // public void tampilMenu() {
    //     System.out.println("Menu: " + nama + " | Harga: " + harga + " | Kategori: " + kategori);
    // }
}

// 2.	Buatlah tiga kelas turunan dari MenuItem: Makanan, Minuman, dan Diskon.
// •	Kelas Makanan dan Minuman adalah subkelas dari MenuItem dan harus memiliki
// atribut tambahan yang sesuai dengan jenisnya (misalnya, jenisMakanan dan jenisMinuman).
// Implementasikan metode tampilMenu() untuk menampilkan informasi khusus tentang makanan dan minuman.

class Makanan extends MenuItem {
    private String jenisMakanan;

    public Makanan(String nama, double harga, String kategori, String jenisMakanan) {
        super(nama, harga, kategori);
        this.jenisMakanan = jenisMakanan;
    }

    // Getter untuk jenisMakanan
    public String getJenisMakanan() {
        return jenisMakanan;
    }

    @Override
    public void tampilMenu() {
        System.out.println("Makanan: " + getNama() + " | Harga: Rp" + getHarga() + " | Jenis: " + jenisMakanan);
    }
}

class Minuman extends MenuItem {
    private String jenisMinuman;

    public Minuman(String nama, double harga, String kategori, String jenisMinuman) {
        super(nama, harga, kategori);
        this.jenisMinuman = jenisMinuman;
    }

    // Getter untuk jenisMinuman
    public String getJenisMinuman() {
        return jenisMinuman;
    }

    @Override
    public void tampilMenu() {
        System.out.println("Minuman: " + getNama() + " | Harga: Rp" + getHarga() + " | Jenis: " + jenisMinuman);
    }
}

// •	Kelas Diskon adalah subkelas dari MenuItem yang akan digunakan untuk menerapkan
// diskon khusus pada menu. Kelas ini harus memiliki atribut diskon (double) dan
// mengimplementasikan metode tampilMenu() untuk menampilkan informasi tentang diskon yang ditawarkan.
class Diskon extends MenuItem {
    private double diskon;

    public Diskon(String nama, double harga, String kategori, double diskon) {
        super(nama, harga, kategori);
        this.diskon = diskon;
    }

    // Getter untuk diskon
    public double getDiskon() {
        return diskon;
    }

    @Override
    public void tampilMenu() {
        System.out.println("Diskon: " + getNama() + " | Persentase Diskon: " + diskon + "%");
    }

    public double hitungHargaDiskon() {
        return getHarga() - (getHarga() * diskon / 100);
    }
}

// 3.	Buatlah sebuah kelas Menu yang akan digunakan untuk mengelola semua item menu
// dalam restoran. Kelas ini harus memiliki atribut berupa sebuah ArrayList untuk
// menyimpan semua item menu.
class Menu {
    private ArrayList<MenuItem> daftarMenu = new ArrayList<>();

    public void tambahMenu(MenuItem item) {
        daftarMenu.add(item);
        System.out.println(item.getNama() + " berhasil ditambahkan ke menu.");
    }

    public void tampilkanMenu() {
        System.out.println("\n--- Daftar Menu ---");
        for (MenuItem item : daftarMenu) {
            item.tampilMenu();
        }
    }

    public MenuItem cariMenu(String nama) throws Exception {
        for (MenuItem item : daftarMenu) {
            if (item.getNama().equalsIgnoreCase(nama)) {
                return item;
            }
        }
        throw new Exception("Item tidak ditemukan!");
    }

    public MenuItem cariDiskon(double harga) throws Exception {
        for (MenuItem item : daftarMenu) {
            if (harga >= item.getHarga() && item instanceof Diskon) {
                return item;
            }
        }
        throw new Exception("Diskon tidak ditemukan!");
    }

    // Menyimpan menu ke file
    public void simpanMenuKeFile(String namaFile) {
        // Membuat folder jika belum ada
        File folder = new File("File Tugas");
        if (!folder.exists()) {
            folder.mkdirs(); // Membuat folder
        }
    
        // Menyimpan file
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(namaFile))) {
            for (MenuItem item : daftarMenu) {
                String data = item.getNama() + "," + item.getHarga() + "," + item.getKategori();
                if (item instanceof Makanan) {
                    data += "," + ((Makanan) item).getJenisMakanan();
                } else if (item instanceof Minuman) {
                    data += "," + ((Minuman) item).getJenisMinuman();
                } else if (item instanceof Diskon) {
                    data += "," + ((Diskon) item).getDiskon();
                }
                writer.write(data);
                writer.newLine();
            }
            System.out.println("Menu berhasil disimpan ke file: " + namaFile);
        } catch (IOException e) {
            System.out.println("Kesalahan saat menyimpan menu: " + e.getMessage());
        }
    }

    // Memuat menu dari file
    public void muatMenuDariFile(String namaFile) {
        try (BufferedReader reader = new BufferedReader(new FileReader(namaFile))) {
            String baris;
            while ((baris = reader.readLine()) != null) {
                String[] data = baris.split(",");
                String nama = data[0];
                double harga = Double.parseDouble(data[1]);
                String kategori = data[2];

                if (kategori.equals("Makanan")) {
                    daftarMenu.add(new Makanan(nama, harga, kategori, data[3]));
                } else if (kategori.equals("Minuman")) {
                    daftarMenu.add(new Minuman(nama, harga, kategori, data[3]));
                } else if (kategori.equals("Diskon")) {
                    double diskon = Double.parseDouble(data[3]);
                    daftarMenu.add(new Diskon(nama, harga, kategori, diskon));
                }
            }
            System.out.println("Menu berhasil dimuat dari file: " + namaFile);
        } catch (IOException e) {
            System.out.println("Kesalahan saat memuat menu: " + e.getMessage());
        }
    }
}

// 4.	Buatlah kelas Pesanan yang akan digunakan untuk mencatat
// pesanan pelanggan. Kelas ini harus memiliki atribut berupa ArrayList
// untuk menyimpan item-item yang dipesan oleh pelanggan.
class Pesanan {
    private ArrayList<MenuItem> daftarPesanan = new ArrayList<>();

    public void tambahPesanan(MenuItem item) {
        // Validasi: pastikan diskon hanya ditambahkan sekali
        if (item instanceof Diskon) {
            // Periksa apakah sudah ada item diskon dalam daftar pesanan
            boolean diskonSudahAda = false;
            for (MenuItem pesananItem : daftarPesanan) {
                if (pesananItem instanceof Diskon) {
                    diskonSudahAda = true;
                    break;
                }
            }
    
            // Jika diskon sudah ada, tampilkan pesan dan tidak tambahkan item
            if (diskonSudahAda) {
                // System.out.println("Diskon hanya bisa diterapkan satu kali.");
                return; // Keluar dari metode jika diskon sudah ada
            }
        }
    
        daftarPesanan.add(item);
        System.out.println(item.getNama() + " ditambahkan ke pesanan.");
    }    

    public void tampilkanPesanan() {
        System.out.println("\n--- Daftar Pesanan ---");
        
        // Menyimpan item-item tanpa diskon
        ArrayList<MenuItem> pesananTanpaDiskon = new ArrayList<>();
        // Menyimpan item-item yang memiliki diskon
        ArrayList<MenuItem> pesananDenganDiskon = new ArrayList<>();
    
        // Memisahkan item-item yang memiliki diskon dan yang tidak
        for (MenuItem item : daftarPesanan) {
            if (item instanceof Diskon) {
                pesananDenganDiskon.add(item);
            } else {
                pesananTanpaDiskon.add(item);
            }
        }
    
        // Menampilkan item tanpa diskon
        for (MenuItem item : pesananTanpaDiskon) {
            item.tampilMenu();
        }
    
        // Menampilkan item dengan diskon terakhir
        for (MenuItem item : pesananDenganDiskon) {
            item.tampilMenu();
        }
    }    

    public double hitungTotal() {
        double total = 0;
        for (MenuItem item : daftarPesanan) {
            if (item instanceof Diskon) {
                total -= (total * ((Diskon) item).getDiskon() / 100);
            } else {
                total += item.getHarga();
            }
        }
        return total;
    }

    // Menyimpan struk pesanan ke file
    public void simpanStrukPesanan(String namaFile) {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(namaFile))) {
            writer.write("--- Struk Pesanan ---");
            writer.newLine();

            // Menyimpan item-item tanpa diskon
            ArrayList<MenuItem> pesananTanpaDiskon = new ArrayList<>();
            // Menyimpan item-item yang memiliki diskon
            ArrayList<MenuItem> pesananDenganDiskon = new ArrayList<>();

            // Memisahkan item-item yang memiliki diskon dan yang tidak
            for (MenuItem item : daftarPesanan) {
                if (item instanceof Diskon) {
                    pesananDenganDiskon.add(item);
                } else {
                    pesananTanpaDiskon.add(item);
                }
            }

            // Menulis item tanpa diskon ke file
            for (MenuItem item : pesananTanpaDiskon) {
                writer.write(item.getNama() + " - Rp" + item.getHarga());
                writer.newLine();
            }

            // Menulis item dengan diskon ke file
            for (MenuItem item : pesananDenganDiskon) {
                writer.write(item.getNama() + " - Rp" + item.getHarga());
                writer.newLine();
            }

            // Menulis total ke file
            writer.write("Total: Rp" + hitungTotal());
            writer.newLine();
            writer.write("--------------------");
            writer.newLine();

            System.out.println("Struk berhasil disimpan ke file: " + namaFile);
        } catch (IOException e) {
            System.out.println("Kesalahan saat menyimpan struk: " + e.getMessage());
        }
    }

    // Memuat struk pesanan dari file
    public void muatStrukPesanan(String namaFile) {
        try (BufferedReader reader = new BufferedReader(new FileReader(namaFile))) {
            String baris;
            // System.out.println("--- Struk Pesanan ---");
            while ((baris = reader.readLine()) != null) {
                System.out.println(baris);
            }
        } catch (IOException e) {
            System.out.println("Kesalahan saat membaca struk: " + e.getMessage());
        }
    }
}

// 5.	Implementasikan konsep inheritance dengan benar antara kelas-kelas ini.
// 6.	Implementasikan konsep encapsulation dengan membatasi akses ke atribut-atribut kelas.
// 7.	Pergunaan pengecualian (exception) yang mungkin terjadi, seperti ketika mencoba
// mengakses item yang tidak ada dalam menu.
// 8.	Program harus memiliki menu utama yang memungkinkan pengguna untuk:
// •	Menambahkan item baru ke menu (makanan, minuman, atau diskon).
// •	Menampilkan menu restoran.
// •	Menerima pesanan dari pelanggan dan mencatatnya.
// •	Menghitung total biaya pesanan dengan mempertimbangkan diskon yang mungkin diterapkan.
// •	Menampilkan struk pesanan pelanggan.
// •	Keluar dari program.
// 9.	Implementasikan operasi I/O dan operasi file untuk menyimpan dan memuat daftar
// menu dari sebuah file teks, dan juga menyimpan struk pesananan pelanggan dan memuat dari file teks.
// 10.	Gunakan struktur keputusan dan pengulangan sesuai dengan kebutuhan, seperti saat
// menampilkan menu dan memproses pesanan.

public class ManajemenRestoran {
    public static void main(String[] args) {
        Menu menu = new Menu();
        Pesanan pesanan = new Pesanan();
        Scanner scanner = new Scanner(System.in);

        // Muat menu dari file saat program dimulai
        menu.muatMenuDariFile("D:/KULIAH/2. TUTON/KHAFID/SEMESTER 5/Pemrograman Berbasis Desktop - LAPRAK/Aktivitas Belajar 12/File Tugas/IO/menu.txt");

        while (true) {
            System.out.println("\n--- Menu Utama ---");
            System.out.println("1. Tambah Menu");
            System.out.println("2. Tampilkan Menu");
            System.out.println("3. Buat Pesanan");
            System.out.println("4. Hitung Total Pesanan");
            System.out.println("5. Simpan Menu ke File");
            System.out.println("6. Simpan Struk Pesanan");
            System.out.println("7. Muat Struk Pesanan");
            System.out.println("8. Keluar");
            System.out.print("Pilih opsi: ");
            int pilihan = scanner.nextInt();
            scanner.nextLine();

            try {
                switch (pilihan) {
                    case 1:
                        System.out.println("1. Makanan");
                        System.out.println("2. Minuman");
                        System.out.println("3. Diskon");
                        System.out.print("Pilih jenis menu: ");
                        int jenis = scanner.nextInt();
                        scanner.nextLine();

                        System.out.print("Nama: ");
                        String nama = scanner.nextLine();
                        System.out.print("Harga: ");
                        double harga = scanner.nextDouble();
                        scanner.nextLine();

                        if (jenis == 1) {
                            System.out.print("Jenis Makanan: ");
                            String jenisMakanan = scanner.nextLine();
                            menu.tambahMenu(new Makanan(nama, harga, "Makanan", jenisMakanan));
                        } else if (jenis == 2) {
                            System.out.print("Jenis Minuman: ");
                            String jenisMinuman = scanner.nextLine();
                            menu.tambahMenu(new Minuman(nama, harga, "Minuman", jenisMinuman));
                        } else if (jenis == 3) {
                            System.out.print("Diskon (%): ");
                            double diskon = scanner.nextDouble();
                            menu.tambahMenu(new Diskon(nama, harga, "Diskon", diskon));
                        }
                        break;
                    case 2:
                        menu.tampilkanMenu();
                        break;
                    case 3:
                        System.out.print("Masukkan nama item yang dipesan: ");
                        String namaItem = scanner.nextLine();
                        MenuItem item = menu.cariMenu(namaItem);
                        pesanan.tambahPesanan(item);

                        MenuItem itemDiskon = menu.cariDiskon(item.getHarga());
                        pesanan.tambahPesanan(itemDiskon);
                        break;
                    case 4:
                        pesanan.tampilkanPesanan();
                        System.out.println("Total Harga: Rp" + pesanan.hitungTotal());
                        break;
                    case 5:
                        menu.simpanMenuKeFile("D:/KULIAH/2. TUTON/KHAFID/SEMESTER 5/Pemrograman Berbasis Desktop - LAPRAK/Aktivitas Belajar 12/File Tugas/IO/menu.txt");
                        break;
                    case 6:
                        pesanan.simpanStrukPesanan("D:/KULIAH/2. TUTON/KHAFID/SEMESTER 5/Pemrograman Berbasis Desktop - LAPRAK/Aktivitas Belajar 12/File Tugas/IO/struk.txt");
                        break;
                    case 7:
                        pesanan.muatStrukPesanan("D:/KULIAH/2. TUTON/KHAFID/SEMESTER 5/Pemrograman Berbasis Desktop - LAPRAK/Aktivitas Belajar 12/File Tugas/IO/struk.txt");
                        break;
                    case 8:
                        System.out.println("Keluar dari program.");
                        return;
                    default:
                        System.out.println("Opsi tidak valid.");
                }
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
        }
    }
}