top of page
Tuyen Nguyen

Abstract Classes và ví dụ Racing Animal

Đã cập nhật: 30 thg 6, 2024

Trong bài viết này, chúng ta sẽ khám phá việc sử dụng lớp trừu tượng trong Java thông qua một ví dụ toàn diện tập trung vào việc định nghĩa các đặc điểm chung của các loại động vật khác nhau trong một hệ thống.


Start with the Animal class here


public abstract class Animal {
    private String name;
    private int speed;

    public Animal(String name, int speed) {
        this.name = name;
        this.speed = speed;
    }

    public String getName() {
        return name;
    }

    public int getSpeed() {
        return speed;
    }

    public abstract boolean canFly();

    @Override
    public String toString() {
        return name + " {" +
                "speed= " + speed +
                '}';
    }
}

Mã nguồn cung cấp một lớp trừu tượng gọi là "Animal" với hai thuộc tính: "name" và "speed," cùng với một hàm tạo và các phương thức getter. Ngoài ra, nó khai báo một phương thức trừu tượng có tên "canFly()," cho thấy bất kỳ lớp con nào mở rộng từ "Animal" phải cung cấp một triển khai cho phương thức này.


Then, create the two subclass "FlyAnimal" and "NonFlyAnimal"


public class FlyAnimal extends Animal{
    public FlyAnimal(String name, int speed) {
        super(name, speed);
    }

    @Override
    public boolean canFly() {
        return true;
    }
}
public class NonFlyAnimal extends Animal{

    public NonFlyAnimal(String name, int speed) {
        super(name, speed);
    }

    @Override
    public boolean canFly() {
        return false;
    }
}

Mã nguồn định nghĩa hai lớp con của "Animal": "FlyAnimal" và "NonFlyAnimal." Mỗi lớp con cung cấp một triển khai cho phương thức trừu tượng "canFly()," chỉ định liệu loài động vật có thể bay hay không.


Now, "AnimalController" is ready from the previous blog

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class AnimalController {

    public void winnerSpeedWithoutWings(List<Animal> animalList){
        Map<Integer, String> mapAnimal = new HashMap<>();
        for (Animal animal : animalList) {
            if(!animal.canFly()){
                mapAnimal.put(animal.getSpeed(), animal.getName());
            }
        }

        int maxSpeed = Collections.max(mapAnimal.keySet());

        for (Map.Entry<Integer, String> entry : mapAnimal.entrySet()) {
            if(entry.getKey() == maxSpeed){
                System.out.printf("Winner is %s, with the speed is %d", entry.getValue(), entry.getKey());
            }
        }

    }
}

Lớp "AnimalController" không thay đổi so với bài viết trước. Nó chứa một phương thức để xác định động vật không bay nhanh nhất trong danh sách các động vật.


Finally, run your code


import java.security.SecureRandom;
import java.util.Arrays;

public class TestAnimal {
    public static void main(String[] args) {
        Animal horse = new NonFlyAnimal("Horse", new SecureRandom().nextInt(100));
        System.out.println(horse.toString());

        Animal dog = new NonFlyAnimal("Dog", new SecureRandom().nextInt(50));
        System.out.println(dog.toString());

        Animal eagle = new FlyAnimal("Eagle", new SecureRandom().nextInt(100));
        System.out.println(eagle.toString());

        Animal duck = new FlyAnimal("Duck", new SecureRandom().nextInt(50));
        System.out.println(duck.toString());

        Animal lion = new NonFlyAnimal("Lion", new SecureRandom().nextInt(100));
        System.out.println(lion.toString());

        AnimalController animalController = new AnimalController();
        animalController.winnerSpeedWithoutWings(Arrays.asList(horse, dog, eagle, duck, lion));
    }
}

Phương thức main tạo ra các thể hiện của các loài động vật khác nhau và thực thi mô phỏng cuộc đua sử dụng "AnimalController."


Conclusion

Trong việc sử dụng lớp trừu tượng so với lớp cụ thể, ta thấy rõ những ưu điểm và nhược điểm của mỗi cách tiếp cận.


Ưu Điểm của Sử Dụng Lớp Trừu Tượng:

  • Trừu Tượng Hóa Hành Vi Chung: Lớp trừu tượng như "Animal" cho phép đóng gói các thuộc tính và hành vi chung của các đối tượng, giúp tái sử dụng mã nguồn và đảm bảo tính nhất quán trong triển khai của các tính năng chung.

  • Bắt Buộc Triển Khai Phương Thức: Các phương thức trừu tượng trong lớp trừu tượng đòi hỏi các lớp con phải triển khai chúng, đảm bảo rằng các lớp con tuân thủ một hợp đồng và cung cấp một cấu trúc rõ ràng cho việc mở rộng chức năng.

  • Tính Linh Hoạt trong Kế Thừa: Các lớp con có thể mở rộng từ một lớp trừu tượng nhưng vẫn có tự do định nghĩa các chức năng bổ sung hoặc ghi đè các phương thức hiện có theo nhu cầu. Điều này thúc đẩy tính linh hoạt và thích ứng trong việc thiết kế các cấu trúc lớp.


Nhược Điểm của Sử Dụng Lớp Trừu Tượng:

  • Giới Hạn về Kế Thừa Đơn: Trong Java, một lớp chỉ có thể kế thừa từ một lớp trừu tượng, hạn chế tính linh hoạt của các cấu trúc lớp. Điều này có thể trở thành một ràng buộc khi xử lý các mối quan hệ phức tạp hoặc khi muốn sử dụng nhiều kế thừa.

  • Kết Nối Chặt Chẽ: Các lớp con được kết nối chặt chẽ với lớp trừu tượng, làm cho việc sửa đổi hệ thống kế thừa sau này trở nên khó khăn. Các thay đổi trong lớp trừu tượng có thể yêu cầu sửa đổi tất cả các lớp con của nó, có thể gây ra vấn đề về bảo trì mã nguồn.

  • Chi Phí Tạo Ra: Định nghĩa một lớp trừu tượng yêu cầu sự cân nhắc cẩn thận về các hành vi và thuộc tính chung. Việc thiết kế trước này có thể dẫn đến một cấu trúc lớp phức tạp hơn cần thiết, tăng khối lượng công việc cho các nhà phát triển. Tóm lại, việc sử dụng lớp trừu tượng như "Animal" mang lại các lợi ích như trừu tượng hóa hành vi chung và bắt buộc triển khai phương thức, nhưng cũng gây ra một số hạn chế như giới hạn về kế thừa và kết nối chặt chẽ. Quyết định sử dụng lớp trừu tượng so với lớp cụ thể phụ thuộc vào yêu cầu cụ thể và xem xét thiết kế của hệ thống.

Comments


bottom of page