Bước chuyển thông minh

Chắc có lẽ tất cả chúng ta đã từng một lần trong đời sử dụng đến Adapter rồi nhỉ? Đó có thể là một thiết bị chuyển từ ổ cắm 2 chân sang 3 chân, có thể là dây chuyển cổng USB sang Type-C, có thể là thiết bị chuyển đổi điện trong bộ sạc, vân vân và mây mây. và đó đều là những bước chuyển thông minh giúp chúng ta vẫn có thể sử dụng các thiết bị hiện đang có mà vẫn tiết kiệm được chi phí.

Bài toán thực tế

Hãy lấy một bài toán thực tế về chương trình phát nhạc trên máy tính của chúng ta. Từ thời xa xưa, khi máy tình còn sơ khai, thì chúng ta chỉ có thể nghe được audio trên trình phát nhạc. Nhưng thế giới đã thay đổi và máy tính cũng mạnh hơn rất rất nhiều lần, nên giờ chúng ta đã có thể xem cải video trên trình phát nhạc. Vậy phải làm thế nào để chúng ta vẫn sử dụng được trình phát nhạc đó để vừa có thể phát được nhạc như cũ mà vừa có thể tích hợp thêm khả năng xem video? Câu trả lời là chúng ta sẽ tạo ra một bộ chuyển đổi (Adapter) để giúp cho các định dạng video có thể mở được trên trình phát nhạc.

Mục tiêu ra đời

Đúng như tính chất của những bộ chuyển đổi, apdater design pattern ra đời nhằm mục tiêu:

  1. Chuyển đổi interface của một class sang interface của một class khác: ví dụ chúng ta cần chuyển đổi interface VideoMediaPlayer sáng interface MediaPlayer
  2. Cho phép các lớp không cùng interface làm việc với nhau mà không làm phá vỡ quy tắc chung: ví dụ lớp AudioPlayer cài đặt interface MediaPlayer có thể làm việc cùng với 2 lớp MP4VideoPlayerVLCVideoPlayer cài đặt interface VideoMediaPlayer cùng để phát đa phương tiện mà không làm ảnh hưởng đến trình phát nhạc đã có sẵn.

Ví dụ

Trở lại với ví dụ trình phát nhạc, chúng ta sẽ cần thiết kế lớp một chút

Sơ đồ lớp

Chúng ta sẽ có 2 interface và 4 lớp:

  1. MediaPlayer: là interface đã có từ trước, chúng ta sẽ không động chạm gì đến interface này
  2. VideoMediaPlayer: là interface mới thêm vào, phục vụ cho tính năng liên quan đến video
  3. MediaAdapter: là lớp chuyển đổi từ VideoMediaPlayer từ MediaPlayer, chính vì thế mà nó phải thừa kế MediaPlayer
  4. AudioPlayer: là lớp chuyên phát nhạc đã có từ trước, chúng ta sẽ cần thay đổi lớp này một chút để gọi đến MediaAdapter trong trường hợp cần phát video
  5. VLCPVideoPlayer: là lớp phục vụ cho phát video liên quan đến vlc
  6. MP4VideoPlayer : là lớp phục vụ cho phát video liên quan đến mp4

Thiết kế lớp đã xong, giờ chúng ta hãy bắt tay vào viết code.

Code

Code cài đặt cũng tương đối đơn giản:

interface MediaPlayer {
    public void play(MediaType mediaType, String fileName);
}

interface VideoMediaPlayer {

    public void playVideo(String fileName);
}

class MediaAdapter implements MediaPlayer {

    private VideoMediaPlayer vlcMediaPlayer = new VLCPVideoPlayer();
    private VideoMediaPlayer mp4MediaPlayer = new MP4VideoPlayer();

    @Override
    public void play(MediaType mediaType, String fileName) {
        if (mediaType == MediaType.VLC) {
            vlcMediaPlayer.playVideo(fileName);
        } 
        else {
            mp4MediaPlayer.playVideo(fileName);
        }
    }
}

class AudioPlayer implements MediaPlayer {

    private final MediaAdapter mediaAdapter = new MediaAdapter();

    @Override
    public void play(MediaType mediaType, String fileName) {
        if (mediaType == MediaType.MP3) {
            System.out.println("Playing MP3 file. Name: " + fileName);
        }
        else {
            mediaAdapter.play(mediaType, fileName);
        }
    }
}

class VLCPVideoPlayer implements VideoMediaPlayer {

    @Override
    public void playVideo(String fileName) {
        System.out.println("Playing VLC file. Name: " + fileName);
    }
}

class MP4VideoPlayer implements VideoMediaPlayer {

    @Override
    public void playVideo(String fileName) {
        System.out.println("Playing MP4 file. Name: " + fileName);
    }
}

Và khi sử dụng sẽ thế này:

MediaPlayer audioPlayer = new AudioPlayer();    
audioPlayer.play(MediaType.MP3, "bong_hoa_nho.mp3");
audioPlayer.play(MediaType.MP4, "bong_hoa_vua.mp4");
audioPlayer.play(MediaType.VLC, "bong_hoa_to.vlc");

Bạn có thể thấy lớp sử dụng không cần quan tâm đến sự có mặt của các lớp cài đặt VideoMediaPlayer , đều này đảm bảo chương trình vẫn hoạt động ổn mà không cần sửa đổi gì lớp sử dụng cả. Ví dụ đầy đủ, bạn có thể tham khảo tại Github của tôi

Tham khảo

  1. Wiki
  2. Ví dụ trong bài