Pola Desain Berorientasi Objek Mediator Vs Observer


95

Saya telah membaca Gang Of Four , untuk memecahkan beberapa masalah saya dan menemukan pola Mediator .

Saya sebelumnya menggunakan Observer dalam proyek saya untuk membuat beberapa aplikasi GUI. Saya agak bingung karena saya tidak menemukan perbedaan besar di antara keduanya. Saya menjelajahi untuk menemukan perbedaannya tetapi tidak dapat menemukan jawaban yang tepat untuk pertanyaan saya.

Bisakah seseorang membantu saya membedakan keduanya dengan beberapa contoh bagus yang dengan jelas membatasi keduanya?


5
Permintaan saya untuk memindahkan pertanyaan ini ke Programmers.StackExchangeditolak, tetapi saya membuat posting serupa di sana karena saya tertarik dengan jawabannya. Anda mungkin menemukan beberapa jawaban yang menarik. :)
Rachel

Untuk contoh JavaScript, Anda dapat melihat jawaban saya untuk pertanyaan serupa .
Alex Pakka

Buku GoF yang asli membahas bahwa di bawah bagian implementasi poin # 8, dengan memberikan contoh a ChangeManageruntuk Observerpola yang digunakan Mediator. Lihat; paginas.fe.up.pt/~aaguiar/as/gof/hires/pat5g.htm#samplecode
robi-y

Jawaban:


106

Pola Observer: Mendefinisikan ketergantungan satu-ke-banyak antar objek sehingga ketika satu objek berubah status, semua tanggungannya diberitahu dan diperbarui secara otomatis.

Pola Mediator: Mendefinisikan sebuah objek yang merangkum bagaimana sekumpulan objek berinteraksi. Mediator mempromosikan kopling longgar dengan menjaga objek agar tidak merujuk satu sama lain secara eksplisit, dan ini memungkinkan Anda memvariasikan interaksinya secara independen.

Sumber: dofactory

Contoh:

Pola pengamat: Kelas A, dapat memiliki nol atau lebih pengamat tipe O yang terdaftar dengannya. Ketika sesuatu di A diubah, itu memberitahu semua pengamat.

Pola mediator: Anda memiliki sejumlah contoh kelas X (atau mungkin bahkan beberapa tipe berbeda: X, Y & Z), dan mereka ingin berkomunikasi satu sama lain (tetapi Anda tidak ingin masing-masing memiliki referensi eksplisit untuk masing-masing other), jadi Anda membuat kelas mediator M. Setiap instance X memiliki referensi ke instance bersama dari M, yang melaluinya dapat berkomunikasi dengan instance X lainnya (atau X, Y, dan Z).


Penjelasan pengamat tampaknya lebih dekat dengan pola perintah daripada pola pengamat
Aun

41

Dalam buku aslinya yang mencetuskan istilah Observer and Mediator, Design Patterns, Elements of Reusable Object-Oriented Software , disebutkan bahwa pola Mediator dapat diimplementasikan dengan menggunakan pola observer. Namun ini juga dapat diterapkan dengan memiliki Rekan (yang kira-kira setara dengan pola Subjek Pengamat) memiliki referensi ke kelas Mediator atau antarmuka Mediator.

Ada banyak kasus ketika Anda ingin menggunakan pola pengamat, kuncinya adalah bahwa suatu objek tidak boleh tahu apa objek lain yang mengamati statusnya.

Mediator sedikit lebih spesifik, ia menghindari kelas berkomunikasi secara langsung tetapi melalui mediator. Ini membantu prinsip Tanggung Jawab Tunggal dengan memungkinkan komunikasi diturunkan ke kelas yang hanya menangani komunikasi.

Contoh Mediator klasik ada di GUI, di mana pendekatan naif mungkin mengarah ke kode pada peristiwa klik tombol yang mengatakan "jika panel Foo dinonaktifkan dan panel Bar memiliki label yang mengatakan" Harap masukkan tanggal "maka jangan panggil server, jika tidak lanjutkan ", di mana dengan pola Mediator dapat dikatakan" Saya hanya sebuah tombol dan tidak memiliki urusan duniawi mengetahui tentang panel Foo dan label pada panel Bar, jadi saya hanya akan bertanya kepada mediator saya jika menelepon server tidak apa-apa sekarang. "

Atau, jika Mediator diimplementasikan menggunakan pola Observer, tombolnya akan berkata "Hai, pengamat (yang akan menyertakan mediator), status saya berubah (seseorang mengklik saya). Lakukan sesuatu jika Anda peduli". Dalam contoh saya yang mungkin kurang masuk akal daripada merujuk langsung ke mediator, tetapi dalam banyak kasus menggunakan pola Observer untuk mengimplementasikan Mediator akan masuk akal, dan perbedaan antara Observer dan Mediator akan lebih pada maksud daripada perbedaan dalam kode itu sendiri.


Saya mencari kata ini "Prinsip Tanggung Jawab Tunggal".
stdout

37

Pengamat

1. Tanpa

  • Klien1 : Hai Subjek , kapan Anda berubah?

  • Klien2 : Kapan Anda mengubah Subjek ? Saya belum memperhatikan!

  • Klien3 : Saya tahu bahwa Subjek telah berubah.

2. Dengan

  • Klien diam.
  • Suatu saat nanti ...
  • Perihal : Klien yang terhormat , saya telah berubah!

Penengah

1. Tanpa

  • Klien1 : Hai Taxi1 , bawa saya kemana.
  • Klien2 : Hai Taxi1 , bawa saya kemana.
  • Klien1 : Hai Taxi2 , bawa saya kemana.
  • Klien2 : Hai Taxi2 , bawa saya kemana.

2. Dengan

  • Klien1 : Hai TaxiCenter , tolong bawa saya Taksi .
  • Klien2 : Hai TaxiCenter , tolong bawa saya Taksi .

2
Contoh mediator Anda adalah pola pabrik, bukan pola mediator
Mohammad Karimi

2
@Pmpr Ini adalah pola desain mediator. TaxiCenter tidak akan membuat taksi, itu membuat taksi tersedia dengan beberapa cara (mungkin setiap taksi menunggu sampai TaxiCenter mengatakan giliran Anda)
Siva R

14

Pola ini digunakan dalam situasi yang berbeda:

Pola mediator digunakan ketika Anda memiliki dua sub-sistem dengan beberapa ketergantungan dan salah satunya akan berubah, dan karena Anda mungkin tidak ingin mengubah sistem yang bergantung pada yang lain, Anda mungkin ingin memperkenalkan mediator yang akan pisahkan ketergantungan di antara mereka. Dengan begitu, ketika salah satu sub-sistem berubah, yang harus Anda lakukan hanyalah memperbarui mediator.

Pola pengamat digunakan ketika sebuah kelas ingin mengizinkan kelas lain untuk mendaftarkan dirinya sendiri dan menerima pemberitahuan atas kejadian, misalnya ButtonListener dll.

Kedua pola ini memungkinkan kopling yang lebih rendah, tetapi sangat berbeda.


7

Mari kita lihat sebuah contoh: anggap Anda ingin membangun dua aplikasi:

  1. Aplikasi obrolan.
  2. Aplikasi operator ambulans darurat.

penengah

Membangun aplikasi obrolan Anda akan memilih mediatorpola desain.

  • Orang tersebut dapat bergabung dan keluar dari obrolan pada waktu tertentu, jadi tidak masuk akal untuk menyimpan referensi langsung antara dua orang yang mengobrol.
  • Kami masih perlu memfasilitasi komunikasi antara dua orang dan memungkinkan mereka mengobrol.

Mengapa kami lebih memilih mediator? lihat saja definisinya:

Dengan pola mediator, komunikasi antar objek dikemas dalam objek mediator. Objek tidak lagi berkomunikasi secara langsung satu sama lain, tetapi berkomunikasi melalui mediator. Ini mengurangi ketergantungan antara objek yang berkomunikasi, sehingga mengurangi kopling.

Bagaimana keajaiban itu bekerja? Pertama kita akan membuat mediator obrolan dan membuat objek orang mendaftar, sehingga akan memiliki dua koneksi arah dengan setiap orang (orang tersebut dapat mengirim pesan menggunakan mediator obrolan karena memiliki akses ke sana, dan mediator obrolan akan mengakses metode yang diterima dari objek orang karena dia juga memiliki akses ke sana)

function Person(name) {
    let self = this;
    this._name = name;
    this._chat = null;

    this._receive(from, message) {        
        console.log("{0}: '{1}'".format(from.name(), message));
    }
    this._send(to, message) {
        this._chat.message(this, to, message);
    }
    return {
        receive: (from, message) => { self._receive(from, message) },
        send: (to, message) => { self._send(to, message) },
        initChat: (chat) => { this._chat = chat; },
        name: () => { return this._name; }
    }
}


function ChatMediator() {
    let self = this;
    this._persons = [];    

    return {
        message: function (from, to, message) {
            if (self._persons.indexOf(to) > -1) {
                self._persons[to].receive(from, message);
            }
        },
        register: function (person) {
            person.initChat(self);
            self._persons.push(person);
        }
        unRegister: function (person) {
            person.initChat(null);
            delete self._persons[person.name()];
        }
    }
};

//Usage:
let chat = new ChatMediator();

let colton = new Person('Colton');
let ronan = new Person('Ronan');

chat.register(colton);
chat.register(ronan);

colton.send(colton, 'Hello there, nice to meet you');
ronan.send(ronan, 'Nice to meet you to');

colton.send(colton, 'Goodbye!');
chat.unRegister(colton);

pengamat

Membangun aplikasi panggilan 911 Anda akan memilih observerpola desain.

  • Setiap observerobjek ambulans ingin diberi tahu ketika ada keadaan darurat, sehingga dia dapat mengarahkan alamat dan memberikan bantuan.
  • Operator darurat observablemenjaga referensi ke masing-masing ambulans observersdan memberi tahu mereka saat bantuan diperlukan (atau menimbulkan peristiwa).

Mengapa kami lebih memilih observer? lihat saja definisinya:

Sebuah objek, disebut subjek, menyimpan daftar tanggungannya, yang disebut pengamat, dan memberi tahu mereka secara otomatis jika ada perubahan status, biasanya dengan memanggil salah satu metode mereka.

function AmbulanceObserver(name) {
    let self = this;
    this._name = name;
    this._send(address) {
        console.log(this._name + ' has been sent to the address: ' + address);
    }
    return {
        send: (address) => { self._send(address) },
        name: () => { return this._name; }
    }
}


function OperatorObservable() {
    let self = this;
    this._ambulances = [];    

    return {
        send: function (ambulance, address) {
            if (self._ambulances.indexOf(ambulance) > -1) {
                self._ambulances[ambulance].send(address);
            }
        },
        register: function (ambulance) {
            self._ambulances.push(ambulance);
        }
        unRegister: function (ambulance) {
            delete self._ambulances[ambulance.name()];
        }
    }
};

//Usage:
let operator = new OperatorObservable();

let amb111 = new AmbulanceObserver('111');
let amb112 = new AmbulanceObserver('112');

operator.register(amb111);
operator.register(amb112);

operator.send(amb111, '27010 La Sierra Lane Austin, MN 000');
operator.unRegister(amb111);

operator.send(amb112, '97011 La Sierra Lane Austin, BN 111');
operator.unRegister(amb112);

Perbedaan:

  1. Obrolan mediatormemiliki komunikasi dua arah antara objek orang (kirim dan terima) di mana operator observablehanya memiliki komunikasi satu arah (Ini memberi tahu ambulans observeruntuk mengemudi dan menyelesaikannya).
  2. Obrolan mediatordapat membuat objek orang berinteraksi di antara mereka (bahkan jika itu bukan komunikasi langsung), ambulans observershanya mendaftar ke observableacara operator .
  3. Setiap objek orang memiliki referensi ke obrolan mediator, dan obrolan mediatortetap mengacu pada setiap orang. Jika ambulans observertidak mengacu pada operator observable, hanya operator yang observablemenyimpan referensi ke setiap ambulans observer.

3
Sedikit terakhir membantu. Mediator dan Observer sama-sama mencapai tujuan yang sama, namun mediator memungkinkan komunikasi dua arah sementara pengamat hanya bekerja satu arah.
kiwicomb123

Persis, senang ini membantu
Shahar Shokrani

Ketika saya membaca tajuknya, saya justru sebaliknya, sebenarnya Pusat panggilan ambulans adalah mediator - yang menerima panggilan dan kemudian mengirim ambulans, polisi dan pemadam kebakaran Dan setiap ambulans di stasiun radio ya adalah pengamat - mereka menunggu acara di radio yang menyentuh mereka Dalam chat: server adalah mediator, setiap klien - pengamat. Apakah menurut Anda?
Maks

7

Meskipun keduanya digunakan untuk cara terorganisir menceritakan tentang perubahan negara, mereka sedikit berbeda secara struktural dan semantik IMO.

Observer digunakan untuk menyiarkan perubahan status suatu objek tertentu, dari objek itu sendiri. Jadi perubahan terjadi di objek pusat yang juga bertanggung jawab untuk memberi isyarat itu. Namun, di Mediator, perubahan status dapat terjadi di objek apa pun, tetapi disiarkan dari mediator. Jadi ada perbedaan aliran. Tapi, menurut saya ini tidak memengaruhi perilaku kode kita. Kita dapat menggunakan satu atau lainnya untuk mencapai perilaku yang sama. Di sisi lain, perbedaan ini mungkin memiliki beberapa pengaruh pada pemahaman konseptual kode.

Lihat, tujuan utama menggunakan pola adalah untuk menciptakan bahasa yang sama di antara para pengembang. Jadi, ketika saya melihat seorang mediator, saya secara pribadi memahami banyak elemen yang mencoba berkomunikasi melalui satu broker / hub untuk mengurangi kebisingan komunikasi (atau untuk mempromosikan SRP) dan setiap objek sama pentingnya dalam hal memiliki kemampuan untuk memberi sinyal perubahan keadaan. Misalnya, pikirkan beberapa pesawat yang mendekati bandara. Masing-masing harus berkomunikasi melalui tiang (mediator) daripada berkomunikasi satu sama lain. (Bayangkan 1000 pesawat berkomunikasi satu sama lain saat mendarat - itu akan berantakan)

Namun, ketika saya melihat pengamat, itu berarti ada beberapa perubahan status yang mungkin saya pedulikan dan harus mendaftar / berlangganan untuk mendengarkan perubahan status tertentu. Ada objek pusat yang bertanggung jawab untuk memberi sinyal perubahan status. Misalnya, jika saya peduli dengan bandara tertentu dalam perjalanan dari A ke B, saya dapat mendaftar ke bandara tersebut untuk menonton beberapa acara yang disiarkan seperti jika ada landasan pacu kosong atau semacamnya.

Semoga sudah jelas.


5

@cdc menjelaskan perbedaan maksud dengan sangat baik.

Saya akan menambahkan beberapa info lebih lanjut di atasnya.

Observer : Mengaktifkan pemberitahuan suatu peristiwa dalam satu objek ke kumpulan objek yang berbeda (contoh kelas yang berbeda)

Mediator : Memusatkan komunikasi antara kumpulan objek, yang dibuat dari kelas tertentu.

Struktur pola Mediator dari pabrik pengolahan :

masukkan deskripsi gambar di sini

Mediator : Mendefinisikan antarmuka untuk komunikasi antar Rekan.

Rekan : Adalah kelas abstrak, yang mendefinisikan acara yang akan dikomunikasikan antar Rekan

ConcreteMediator : Menerapkan perilaku kooperatif dengan mengoordinasikan objek Rekan dan mempertahankan rekannya

ConcreteColleague : Menerapkan operasi notifikasi yang diterima melalui Mediator , yang dibuat oleh Rekan lainnya

Satu contoh dunia nyata:

Anda memelihara jaringan komputer dalam topologi Mesh . Jika komputer baru ditambahkan atau komputer yang sudah ada dihapus, semua komputer lain di jaringan itu harus mengetahui tentang dua peristiwa ini.

Mari kita lihat bagaimana pola Mediator cocok dengannya.

Potongan kode:

import java.util.List;
import java.util.ArrayList;

/* Define the contract for communication between Colleagues. 
   Implementation is left to ConcreteMediator */
interface Mediator{
    public void register(Colleague colleague);
    public void unregister(Colleague colleague);
}
/* Define the contract for notification events from Mediator. 
   Implementation is left to ConcreteColleague
*/
abstract class Colleague{
    private Mediator mediator;
    private String name;

    public Colleague(Mediator mediator,String name){
        this.mediator = mediator;
        this.name = name;
    }
    public String toString(){
        return name;
    }
    public abstract void receiveRegisterNotification(Colleague colleague);
    public abstract void receiveUnRegisterNotification(Colleague colleague);    
}
/*  Process notification event raised by other Colleague through Mediator.   
*/
class ComputerColleague extends Colleague {
    private Mediator mediator;

    public ComputerColleague(Mediator mediator,String name){
        super(mediator,name);
    }
    public  void receiveRegisterNotification(Colleague colleague){
        System.out.println("New Computer register event with name:"+colleague+
        ": received @"+this);
        // Send further messages to this new Colleague from now onwards
    }
    public  void receiveUnRegisterNotification(Colleague colleague){
        System.out.println("Computer left unregister event with name:"+colleague+
        ":received @"+this);
        // Do not send further messages to this Colleague from now onwards
    }
}
/* Act as a central hub for communication between different Colleagues. 
   Notifies all Concrete Colleagues on occurrence of an event
*/
class NetworkMediator implements Mediator{
    List<Colleague> colleagues = new ArrayList<Colleague>();

    public NetworkMediator(){

    }

    public void register(Colleague colleague){
        colleagues.add(colleague);
        for (Colleague other : colleagues){
            if ( other != colleague){
                other.receiveRegisterNotification(colleague);
            }
        }
    }
    public void unregister(Colleague colleague){
        colleagues.remove(colleague);
        for (Colleague other : colleagues){
            other.receiveUnRegisterNotification(colleague);
        }
    }
}

public class MediatorPatternDemo{
    public static void main(String args[]){
        Mediator mediator = new NetworkMediator();
        ComputerColleague colleague1 = new ComputerColleague(mediator,"Eagle");
        ComputerColleague colleague2 = new ComputerColleague(mediator,"Ostrich");
        ComputerColleague colleague3 = new ComputerColleague(mediator,"Penguin");
        mediator.register(colleague1);
        mediator.register(colleague2);
        mediator.register(colleague3);
        mediator.unregister(colleague1);
    }
}

keluaran:

New Computer register event with name:Ostrich: received @Eagle
New Computer register event with name:Penguin: received @Eagle
New Computer register event with name:Penguin: received @Ostrich
Computer left unregister event with name:Eagle:received @Ostrich
Computer left unregister event with name:Eagle:received @Penguin

Penjelasan:

  1. Eagle ditambahkan ke jaringan pada awalnya melalui acara pendaftaran. Tidak ada pemberitahuan ke kolega lain karena Eagle adalah yang pertama.
  2. Ketika Ostrich ditambahkan ke jaringan, Eagle diberi tahu: Baris 1 keluaran telah ditampilkan sekarang.
  3. Saat Penguin ditambahkan ke jaringan, baik Eagle maupun Ostrich telah diberi tahu: Baris 2 dan Baris 3 keluaran telah ditampilkan sekarang.
  4. Saat Eagle meninggalkan jaringan karena acara pembatalan pendaftaran, Burung Unta dan Penguin telah diberi tahu. Baris 4 dan Baris 5 keluaran dirender sekarang.

2

Bagaimana dengan penjelasan ini Secara teknis baik Observer dan Mediator adalah sama dan digunakan untuk menyediakan cara yang terpisah untuk komunikasi komponen, tetapi penggunaannya berbeda.

Saat obeserver memberi tahu komponen yang dilanggan tentang perubahan status (pembuatan data db baru, misalnya), mediator perintah komponen terdaftar untuk melakukan sesuatu yang berkaitan dengan alur logika bisnis (mengirim email ke pengguna untuk menyetel ulang kata sandi).

Pengamat

  • Konsumen notifikasi bertanggung jawab untuk berlangganan untuk menerima notifikasi
  • Pemrosesan pemberitahuan bukan bagian dari alur bisnis

Penengah

  • Pendaftaran eksplisit diperlukan untuk menghubungkan "penerbit" dan "konsumen"
  • Pemrosesan pemberitahuan adalah bagian dari aliran bisnis tertentu
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.