Pahami “Pola Penghias” dengan contoh dunia nyata

167

Saya sedang mempelajari Pola Dekorator seperti yang didokumentasikan di GOF .

Tolong, bantu saya memahami Pola Dekorator . Bisakah seseorang memberikan contoh kasus penggunaan di mana ini berguna di dunia nyata?

odiseh
sumber
8
Anda dapat menemukan di sini beberapa contoh dunia nyata di Java API: stackoverflow.com/questions/1673841/…
BalusC
Artikel yang menunjukkan manfaat pola dekorator dengan contoh sederhana: dzone.com/articles/is-inheritance-dead
nbilal

Jawaban:

226

Pola dekorator mencapai tujuan tunggal yaitu secara dinamis menambahkan tanggung jawab pada objek apa pun.

Pertimbangkan sebuah toko pizza. Di toko pizza mereka akan menjual beberapa varietas pizza dan mereka juga akan menyediakan topping di menu. Sekarang bayangkan situasi di mana jika toko pizza harus memberikan harga untuk setiap kombinasi pizza dan topping. Bahkan jika ada empat pizza dasar dan 8 topping berbeda, aplikasi akan menjadi gila mempertahankan semua kombinasi pizza dan topping konkret ini.

Di sinilah pola dekorator.

Sesuai pola dekorator, Anda akan menerapkan topping karena dekorator dan pizza akan didekorasi oleh dekorator topping itu. Praktis setiap pelanggan menginginkan topping dari keinginannya dan jumlah tagihan akhir akan terdiri dari pizza dasar dan topping tambahan yang dipesan. Setiap dekorator topping akan tahu tentang pizza yang sedang didekorasi dan harganya. Metode GetPrice () dari objek Topping akan mengembalikan harga kumulatif pizza dan topping.

EDIT

Berikut adalah contoh kode penjelasan di atas.

public abstract class BasePizza
{
    protected double myPrice;

    public virtual double GetPrice()
    {
        return this.myPrice;
    }
}

public abstract class ToppingsDecorator : BasePizza
{
    protected BasePizza pizza;
    public ToppingsDecorator(BasePizza pizzaToDecorate)
    {
        this.pizza = pizzaToDecorate;
    }

    public override double GetPrice()
    {
        return (this.pizza.GetPrice() + this.myPrice);
    }
}

class Program
{
    [STAThread]
    static void Main()
    {
        //Client-code
        Margherita pizza = new Margherita();
        Console.WriteLine("Plain Margherita: " + pizza.GetPrice().ToString());

        ExtraCheeseTopping moreCheese = new ExtraCheeseTopping(pizza);
        ExtraCheeseTopping someMoreCheese = new ExtraCheeseTopping(moreCheese);
        Console.WriteLine("Plain Margherita with double extra cheese: " + someMoreCheese.GetPrice().ToString());

        MushroomTopping moreMushroom = new MushroomTopping(someMoreCheese);
        Console.WriteLine("Plain Margherita with double extra cheese with mushroom: " + moreMushroom.GetPrice().ToString());

        JalapenoTopping moreJalapeno = new JalapenoTopping(moreMushroom);
        Console.WriteLine("Plain Margherita with double extra cheese with mushroom with Jalapeno: " + moreJalapeno.GetPrice().ToString());

        Console.ReadLine();
    }
}

public class Margherita : BasePizza
{
    public Margherita()
    {
        this.myPrice = 6.99;
    }
}

public class Gourmet : BasePizza
{
    public Gourmet()
    {
        this.myPrice = 7.49;
    }
}

public class ExtraCheeseTopping : ToppingsDecorator
{
    public ExtraCheeseTopping(BasePizza pizzaToDecorate)
        : base(pizzaToDecorate)
    {
        this.myPrice = 0.99;
    }
}

public class MushroomTopping : ToppingsDecorator
{
    public MushroomTopping(BasePizza pizzaToDecorate)
        : base(pizzaToDecorate)
    {
        this.myPrice = 1.49;
    }
}

public class JalapenoTopping : ToppingsDecorator
{
    public JalapenoTopping(BasePizza pizzaToDecorate)
        : base(pizzaToDecorate)
    {
        this.myPrice = 1.49;
    }
}
ini. __curious_geek
sumber
104
Jangan suka pola ini sedikit pun. Mungkin itu contohnya. Masalah utama yang saya miliki dalam hal OOD adalah topping bukan pizza . Meminta topping untuk harga pizza yang diterapkan hanya tidak cocok dengan saya. Ini adalah contoh yang sangat bijaksana dan detail, jadi saya tidak bermaksud menjatuhkan Anda untuk itu.
Tom W
39
@ Tom Saya pikir bagian dari masalah adalah penamaan. Semua kelas "Topping" harus disebut "PizzaWith <Topping>". Misalnya, "PizzaWithMushrooms".
Josh Noe
2
Menurut pendapat saya, dekorator paling baik digunakan selurus mungkin. Maksud saya sesedikit "dekorator membungkus dekorator" mungkin. Jadi mungkin contoh ini bukan yang paling tepat. Tapi itu cukup menyeluruh, yang bagus.
thekingoftruth
17
Dari perspektif lain ini bahkan tidak dekat dengan "dunia nyata". Di dunia nyata Anda tidak harus mengkompilasi ulang setiap kali Anda perlu menambahkan menu topping baru (atau mengubah harga). Topping (biasanya) disimpan dalam database dan dengan demikian membuat contoh di atas tidak berguna.
Stelios Adamantidis
4
^ Ini. Saya pikir inilah yang selama ini mengganggu saya saat mempelajari pola ini. Jika saya adalah perusahaan perangkat lunak dan menulis perangkat lunak pizza shop, saya tidak ingin harus mengkompilasi ulang dan mengatur ulang setiap kali. Saya ingin menambahkan baris dalam tabel di backend atau sesuatu yang akan dengan mudah memenuhi kebutuhan mereka. Kata baik, @Stelios Adamantidis. Saya kira pola kekuatan terbesar meskipun akan memodifikasi kelas pihak ke-3 lalu.
Canucklesandwich
33

Ini adalah contoh sederhana menambahkan perilaku baru ke objek yang ada secara dinamis, atau pola dekorator. Karena sifat bahasa dinamis seperti Javascript, pola ini menjadi bagian dari bahasa itu sendiri.

// Person object that we will be decorating with logging capability
var person = {
  name: "Foo",
  city: "Bar"
};

// Function that serves as a decorator and dynamically adds the log method to a given object
function MakeLoggable(object) {
  object.log = function(property) {
    console.log(this[property]);
  }
}

// Person is given the dynamic responsibility here
MakeLoggable(person);

// Using the newly added functionality
person.log('name');

Anurag
sumber
Sederhana dan tepat! Contoh yang bagus!
nagendra547
1
Saya tidak berpikir bahwa konsep Pola Penghias berlaku di sini. Sebenarnya itu bukan pola sama sekali !. Ya, Anda menambahkan metode baru saat runtime. Dan mungkin di dalam switchatau sederhana if, Anda akan dapat mengklaim bahwa ini adalah contoh yang bagus dari menambahkan perilaku secara dinamis ke kelas. TETAPI, kita membutuhkan setidaknya dua kelas untuk mendefinisikan dekorator dan benda-benda yang dihiasi dalam pola ini.
Iman
1
@Zich Saya mengerti tidak ada dekorator dalam contoh saya tapi itu mudah diperbaiki dengan menambahkan fungsi yang berfungsi sebagai dekorator. Tetapi ada benda yang dihiasi dalam contoh saya. Apakah polanya mengatakan di mana saja bahwa Anda memerlukan dua kelas secara khusus?
Anurag
18

Perlu dicatat bahwa model Java i / o didasarkan pada pola dekorator. Layering pembaca ini di atas pembaca itu di atas ... adalah contoh dunia nyata dekorator.

frankc
sumber
Apakah ada contoh lain di API publik nyata? Ini satu-satunya yang saya tahu.
Josiah Yoder
Tampaknya semua fungsi pembungkus di alam memiliki semacam pola dekorator yang dibangun, apakah itu yang saya pikirkan?
Harvey Lin
Contoh yang baik !!
nagendra547
8

Contoh - Skenario- Katakanlah Anda sedang menulis modul enkripsi. Enkripsi ini dapat mengenkripsi file yang jelas menggunakan DES - standar enkripsi data. Demikian pula, dalam suatu sistem Anda dapat memiliki enkripsi sebagai standar enkripsi AES - Advance. Anda juga dapat memiliki kombinasi enkripsi - DES Pertama, lalu AES. Atau Anda dapat memiliki AES pertama, lalu DES.

Diskusi- Bagaimana Anda akan memenuhi situasi ini? Anda tidak dapat terus membuat objek kombinasi tersebut - misalnya - AES dan DES - total 4 kombinasi. Dengan demikian, Anda perlu memiliki 4 objek individual. Ini akan menjadi kompleks karena jenis enkripsi akan meningkat.

Solusi - Terus susun kombinasi - tumpukan tergantung pada kebutuhan - pada saat run time. Keuntungan lain dari pendekatan tumpukan ini adalah Anda dapat melepasnya dengan mudah.

Inilah solusinya - dalam C ++.

Pertama, Anda memerlukan kelas dasar - unit dasar tumpukan. Anda dapat berpikir sebagai dasar tumpukan. Dalam contoh ini, file itu jelas. Mari kita ikuti selalu polimorfisme. Jadikan pertama sebagai kelas antarmuka dari unit dasar ini. Dengan cara ini, Anda bisa menerapkannya sesuai keinginan. Juga, Anda tidak perlu memikirkan ketergantungan sambil memasukkan unit mendasar ini.

Inilah kelas antarmuka -

class IclearData
{
public:

    virtual std::string getData() = 0;
    virtual ~IclearData() = 0;
};

IclearData::~IclearData()
{
    std::cout<<"Destructor called of IclearData"<<std::endl;
}

Sekarang, terapkan kelas antarmuka ini -

class clearData:public IclearData
{
private:

    std::string m_data;

    clearData();

    void setData(std::string data)
        {
            m_data = data;
        }

public:

    std::string getData()
    {
        return m_data;
    }

    clearData(std::string data)
    {
        setData(data);
    }

    ~clearData()
    {
        std::cout<<"Destructor of clear Data Invoked"<<std::endl;
    }

};

Sekarang, mari kita buat kelas abstrak dekorator - yang dapat diperluas untuk menciptakan segala jenis rasa - di sini rasanya adalah jenis enkripsi. Kelas abstrak dekorator ini terkait dengan kelas dasar. Dengan demikian, dekorator "adalah" semacam kelas antarmuka. Jadi, Anda perlu menggunakan warisan.

class encryptionDecorator: public IclearData
{

protected:
    IclearData *p_mclearData;

    encryptionDecorator()
    {
      std::cout<<"Encryption Decorator Abstract class called"<<std::endl;
    }

public:

    std::string getData()
    {
        return p_mclearData->getData();
    }

    encryptionDecorator(IclearData *clearData)
    {
        p_mclearData = clearData;
    }

    virtual std::string showDecryptedData() = 0;

    virtual ~encryptionDecorator() = 0;

};

encryptionDecorator::~encryptionDecorator()
{
    std::cout<<"Encryption Decorator Destructor called"<<std::endl;
}

Sekarang, mari kita buat kelas dekorator beton - Jenis enkripsi - AES -

const std::string aesEncrypt = "AES Encrypted ";

class aes: public encryptionDecorator
{

private:

    std::string m_aesData;

    aes();

public:

    aes(IclearData *pClearData): m_aesData(aesEncrypt)
    {
        p_mclearData = pClearData;
        m_aesData.append(p_mclearData->getData());
    }

    std::string getData()
        {
            return m_aesData;
        }

    std::string showDecryptedData(void)
    {
        m_aesData.erase(0,m_aesData.length());
        return m_aesData;
    }

};

Sekarang, katakanlah tipe dekoratornya adalah DES -

const std :: string desEncrypt = "DES Encrypted";

class des: public encryptionDecorator
{

private:

    std::string m_desData;

    des();

public:

    des(IclearData *pClearData): m_desData(desEncrypt)
    {
        p_mclearData = pClearData;
        m_desData.append(p_mclearData->getData());
    }

    std::string getData(void)
        {
            return m_desData;
        }

    std::string showDecryptedData(void)
    {
        m_desData.erase(0,desEncrypt.length());
        return m_desData;
    }

};

Mari kita membuat kode klien untuk menggunakan kelas dekorator ini -

int main()
{
    IclearData *pData = new clearData("HELLO_CLEAR_DATA");

    std::cout<<pData->getData()<<std::endl;


    encryptionDecorator *pAesData = new aes(pData);

    std::cout<<pAesData->getData()<<std::endl;

    encryptionDecorator *pDesData = new des(pAesData);

    std::cout<<pDesData->getData()<<std::endl;

    /** unwind the decorator stack ***/
    std::cout<<pDesData->showDecryptedData()<<std::endl;

    delete pDesData;
    delete pAesData;
    delete pData;

    return 0;
}

Anda akan melihat hasil berikut -

HELLO_CLEAR_DATA
Encryption Decorator Abstract class called
AES Encrypted HELLO_CLEAR_DATA
Encryption Decorator Abstract class called
DES Encrypted AES Encrypted HELLO_CLEAR_DATA
AES Encrypted HELLO_CLEAR_DATA
Encryption Decorator Destructor called
Destructor called of IclearData
Encryption Decorator Destructor called
Destructor called of IclearData
Destructor of clear Data Invoked
Destructor called of IclearData

Di sini adalah diagram UML - Representasi kelas untuk itu. Dalam hal ini, Anda ingin melewatkan kode dan fokus pada aspek desain.

masukkan deskripsi gambar di sini

tangkas
sumber
1
bukankah contohnya lebih cocok strategy pattern?
exexzian
@exexzian Ya, siswa saya secara konsisten menyarankan daftar strategi kepada saya untuk jenis masalah ini, dan rasanya seperti solusi terbersih untuk saya juga.
Josiah Yoder
Tidak, dengan pola strategi Anda tidak dapat menggabungkan metode enkripsi. Oleh karena itu Anda harus membuat kelas strategi untuk setiap kemungkinan kombinasi.
deetz
4

Pola dekorator membantu Anda mengubah atau mengonfigurasi fungsionalitas objek Anda dengan merantai dengan subclass serupa lainnya dari objek ini.

Contoh terbaik adalah kelas InputStream dan OutputStream dalam paket java.io

    File file=new File("target","test.txt");
    FileOutputStream fos=new FileOutputStream(file);
    BufferedOutputStream bos=new BufferedOutputStream(fos);
    ObjectOutputStream oos=new ObjectOutputStream(bos);


    oos.write(5);
    oos.writeBoolean(true);
    oos.writeBytes("decorator pattern was here.");


//... then close the streams of course.
huseyin
sumber
Dalam hal ini, rantai panggilan dimulai pada ObjectOutputStream, kemudian naik ke kelas File, kemudian kelas File mengembalikan nilai, lalu tiga subclass lainnya menambahkan semuanya dan akhirnya, nilai metode ObjectOutputStream mengembalikannya, adalah itu benar
Harvey Lin
3

Apa itu Pola Desain Penghias di Jawa.

Definisi formal dari pola Dekorator dari buku GoF (Pola Desain: Elemen Reusable Object-Oriented Software, 1995, Pearson Education, Inc. Penerbitan sebagai Pearson Addison Wesley) mengatakan Anda bisa,

"Lampirkan tanggung jawab tambahan pada objek secara dinamis. Dekorator memberikan alternatif yang fleksibel untuk subklasifikasi untuk memperluas fungsionalitas."

Katakanlah kita memiliki Pizza dan kita ingin menghiasinya dengan topping seperti Chicken Masala, Onion dan Mozzarella Cheese. Mari kita lihat bagaimana mengimplementasikannya di Java ...

Program untuk menunjukkan bagaimana menerapkan Pola Desain Dekorator di Jawa.

Pizza.java:

<!-- language-all: lang-html -->

package com.hubberspot.designpattern.structural.decorator;

public class Pizza {

public Pizza() {

}

public String description(){
    return "Pizza";
}

}



package com.hubberspot.designpattern.structural.decorator;

public abstract class PizzaToppings extends Pizza {

public abstract String description();

}

package com.hubberspot.designpattern.structural.decorator;

public class ChickenMasala extends PizzaToppings {

private Pizza pizza;

public ChickenMasala(Pizza pizza) {
    this.pizza = pizza;
}

@Override
public String description() {
    return pizza.description() + " with chicken masala, ";
}

}



package com.hubberspot.designpattern.structural.decorator;

public class MozzarellaCheese extends PizzaToppings {

private Pizza pizza;

public MozzarellaCheese(Pizza pizza) {
    this.pizza = pizza;
}

@Override
public String description() {
    return pizza.description() + "and mozzarella cheese.";
}
}



package com.hubberspot.designpattern.structural.decorator;

public class Onion extends PizzaToppings {

private Pizza pizza;

public Onion(Pizza pizza) {
    this.pizza = pizza;
}

@Override
public String description() {
    return pizza.description() + "onions, ";
}

}



package com.hubberspot.designpattern.structural.decorator;

public class TestDecorator {

public static void main(String[] args) {

    Pizza pizza = new Pizza();

    pizza = new ChickenMasala(pizza);
    pizza = new Onion(pizza);
    pizza = new MozzarellaCheese(pizza);

    System.out.println("You're getting " + pizza.description());

}

}
Jonty
sumber
3

Saya telah menggunakan pola dekorator secara luas di tempat kerja saya. Saya membuat posting di blog saya tentang cara menggunakannya dengan logging.

Ismael
sumber
Saya tidak suka Anda hanya melemparkan tautan sebagai jawaban. Tetapi artikel Blog Anda, sangat membantu, sehingga saya hanya perlu melakukan upvote :). Sekarang saya benar-benar memahaminya. Semua orang datang dengan pizza, dan Anda dengan contoh sempurna.
Niklas Raab
2

Pola dekorator memungkinkan Anda menambahkan perilaku secara dinamis ke objek.

Mari kita ambil contoh di mana Anda perlu membangun aplikasi yang menghitung harga berbagai jenis burger. Anda perlu menangani variasi burger yang berbeda, seperti "besar" atau "dengan keju", yang masing-masing memiliki harga relatif terhadap burger dasar. Misalnya, tambahkan $ 10 untuk burger dengan keju, tambahkan ekstra $ 15 untuk burger besar, dll.

Dalam hal ini Anda mungkin tergoda untuk membuat subclass untuk menangani ini. Kami mungkin mengungkapkan ini di Ruby sebagai:

class Burger
  def price
    50
  end
end

class BurgerWithCheese < Burger
  def price
    super + 15
  end
end

Dalam contoh di atas, kelas BurgerWithCheese mewarisi dari Burger, dan mengganti metode harga untuk menambahkan $ 15 ke harga yang ditentukan dalam kelas super. Anda juga akan membuat kelas LargeBurger dan menentukan harga relatif terhadap Burger. Tetapi Anda juga perlu mendefinisikan kelas baru untuk kombinasi "besar" dan "dengan keju".

Sekarang apa yang terjadi jika kita perlu menyajikan "burger dengan kentang goreng"? Kami sudah memiliki 4 kelas untuk menangani kombinasi tersebut, dan kami perlu menambahkan 4 lagi untuk menangani semua kombinasi dari 3 properti - "besar", "dengan keju" dan "dengan kentang goreng". Kami membutuhkan 8 kelas sekarang. Tambahkan properti lain dan kita perlu 16. Ini akan tumbuh 2 ^ n.

Sebagai gantinya, mari kita coba mendefinisikan BurgerDecorator yang mengambil objek Burger:

class BurgerDecorator
  def initialize(burger)
    self.burger = burger
  end
end

class BurgerWithCheese < BurgerDecorator
  def price
    self.burger.price + 15
  end
end

burger = Burger.new
cheese_burger = BurgerWithCheese.new(burger)
cheese_burger.price   # => 65

Dalam contoh di atas, kami telah membuat kelas BurgerDecorator, dari mana kelas BurgerWithCheese mewarisi. Kami juga dapat mewakili variasi "besar" dengan membuat kelas LargeBurger. Sekarang kita bisa mendefinisikan burger besar dengan keju saat runtime sebagai:

b = LargeBurger.new(cheese_burger)
b.price  # => 50 + 15 + 20 = 85

Ingat bagaimana menggunakan pewarisan untuk menambahkan variasi "dengan kentang goreng" akan melibatkan penambahan 4 subkelas lainnya? Dengan dekorator, kami hanya akan membuat satu kelas baru, BurgerWithFries, untuk menangani variasi baru dan menangani ini saat runtime. Setiap properti baru akan membutuhkan lebih banyak dekorator untuk mencakup semua permutasi.

PS. Ini adalah versi singkat dari artikel yang saya tulis tentang penggunaan Pola Penghias di Ruby , yang dapat Anda baca jika Anda ingin mengetahui contoh yang lebih rinci.

Nithin
sumber
2

Penghias:

  1. Tambahkan perilaku ke objek saat run time . Warisan adalah kunci untuk mencapai fungsi ini, yang merupakan keuntungan dan kerugian dari pola ini.
  2. Ini meningkatkan perilaku antarmuka.
  3. Dekorator dapat dilihat sebagai Komposit degenerasi dengan hanya satu komponen. Namun, Dekorator menambahkan tanggung jawab tambahan - tidak dimaksudkan untuk agregasi objek.
  4. Kelas Dekorator menyatakan hubungan komposisi dengan antarmuka LCD (Penyingkat Kelas Terendah), dan anggota data ini diinisialisasi dalam konstruktornya.
  5. Dekorator dirancang untuk memungkinkan Anda menambahkan tanggung jawab pada objek tanpa subklasifikasi

Lihat artikel pembuatan sumber untuk lebih jelasnya.

Dekorator (Abstrak) : ini adalah kelas / antarmuka abstrak, yang mengimplementasikan antarmuka komponen. Ini berisi antarmuka Komponen. Dengan tidak adanya kelas ini, Anda memerlukan banyak subkelas ConcreteDecorators untuk kombinasi yang berbeda. Komposisi komponen mengurangi subkelas yang tidak perlu.

Contoh JDK:

BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("a.txt")));
while(bis.available()>0)
{
        char c = (char)bis.read();
        System.out.println("Char: "+c);;
}

Lihat pertanyaan SE di bawah ini untuk diagram UML dan contoh kode.

Pola dekorator untuk IO

Artikel yang berguna:

journaldev

wikipedia

Contoh kata asli dari pola Penghias: VendingMachineDecorator telah dijelaskan @

Kapan Menggunakan Pola Penghias?

Beverage beverage = new SugarDecorator(new LemonDecorator(new Tea("Assam Tea")));
beverage.decorateBeverage();

beverage = new SugarDecorator(new LemonDecorator(new Coffee("Cappuccino")));
beverage.decorateBeverage();

Dalam contoh di atas, Teh atau Kopi (Minuman) telah didekorasi dengan Gula dan Lemon.

Ravindra babu
sumber
2

Pola dekorator mencapai tujuan tunggal yaitu secara dinamis menambahkan tanggung jawab pada objek apa pun .

Model Java I / O didasarkan pada pola dekorator.

Java IO sebagai pola dekorator

ChandraBhan Singh
sumber
1

Beberapa waktu yang lalu saya telah refactored basis kode menggunakan pola dekorator, jadi saya akan mencoba menjelaskan kasus penggunaan.

Mari kita asumsikan kita memiliki seperangkat layanan dan berdasarkan apakah pengguna telah memperoleh lisensi layanan tertentu, kita perlu memulai layanan.

Semua layanan memiliki antarmuka yang sama

interface Service {
  String serviceId();
  void init() throws Exception;
  void start() throws Exception;
  void stop() throws Exception;
}

Pra Refactoring

abstract class ServiceSupport implements Service {
  public ServiceSupport(String serviceId, LicenseManager licenseManager) {
    // assign instance variables
  }

  @Override
  public void init() throws Exception {
    if (!licenseManager.isLicenseValid(serviceId)) {
       throw new Exception("License not valid for service");
    }
    // Service initialization logic
  }
}

Jika Anda mengamati dengan seksama, ServiceSupporttergantung pada LicenseManager. Tetapi mengapa harus bergantung LicenseManager? Bagaimana jika kami membutuhkan layanan latar belakang yang tidak perlu memeriksa informasi lisensi. Dalam situasi saat ini kita harus entah bagaimana berlatih LicenseManageruntuk kembali trueke layanan latar belakang. Pendekatan ini tampaknya tidak baik bagi saya. Menurut saya cek lisensi dan logika lainnya saling orthogonal.

Jadi Pola Penghias datang untuk menyelamatkan dan di sini mulai refactoring dengan TDD.

Posting Refactoring

class LicensedService implements Service {
  private Service service;
  public LicensedService(LicenseManager licenseManager, Service service) {
    this.service = service;
  }

  @Override
  public void init() {
    if (!licenseManager.isLicenseValid(service.serviceId())) {
      throw new Exception("License is invalid for service " + service.serviceId());
    }
    // Delegate init to decorated service
    service.init();
  }

  // override other methods according to requirement
}

// Not concerned with licensing any more :)
abstract class ServiceSupport implements Service {
  public ServiceSupport(String serviceId) {
    // assign variables
  }

  @Override
  public void init() {
    // Service initialization logic
  }
}

// The services which need license protection can be decorated with a Licensed service
Service aLicensedService = new LicensedService(new Service1("Service1"), licenseManager);
// Services which don't need license can be created without one and there is no need to pass license related information
Service aBackgroundService = new BackgroundService1("BG-1");

Takeaways

  • Kohesi kode menjadi lebih baik
  • Pengujian unit menjadi lebih mudah, karena tidak perlu mengejek perizinan saat menguji ServiceSupport
  • Tidak perlu melewati lisensi dengan pemeriksaan khusus untuk layanan latar belakang
  • Pembagian tanggung jawab yang tepat
Narendra Pathai
sumber
1

Mari kita ambil contoh PubG. Senapan serbu bekerja paling baik dengan zoom 4x dan sementara kita berada di atasnya, kita juga akan membutuhkan kompensator dan penekan. Ini akan mengurangi mundur dan mengurangi suara tembakan serta gema. Kami perlu menerapkan fitur ini di mana kami akan memungkinkan pemain untuk membeli senjata favorit mereka dan aksesori mereka. Pemain dapat membeli pistol atau aksesori atau semua aksesori dan mereka akan dibebankan sesuai.

Mari kita lihat bagaimana pola dekorator diterapkan di sini:

Misalkan seseorang ingin membeli SCAR-L dengan ketiga aksesori yang disebutkan di atas.

  1. Ambil objek SCAR-L
  2. Hiasi (atau tambah) SCAR-L dengan objek zoom 4x
  3. Hiasi SCAR-L dengan benda penekan
  4. Hiasi SCAR-L dengan benda kompresor
  5. Panggil metode biaya dan biarkan masing-masing objek mendelegasikan untuk menambah biaya menggunakan metode biaya aksesori

Ini akan mengarah ke diagram kelas seperti ini:

Pola dekorator di tempat kerja

Sekarang, kita dapat memiliki kelas seperti ini:

public abstract class Gun {     
    private Double cost;    
    public Double getCost() {           
        return cost;        
       }    
    }

public abstract class GunAccessories extends Gun {  }

public class Scarl extends Gun {    
    public Scarl() {            
        cost = 100;
        }   
     }

public class Suppressor extends GunAccessories {        
    Gun gun;        
    public Suppressor(Gun gun) {            
    cost = 5;           
    this.gun = gun;     
    }               
    public double getCost(){            
        return cost + gun.getCost();
    }
}

public class GunShop{   
    public static void main(String args[]){         
    Gun scarl = new Scarl();                
    scarl = new Supressor(scarl);
    System.out.println("Price is "+scarl.getCost());
    }      
}

Kami juga dapat menambahkan aksesori lain dan menghias Pistol kami.

Referensi:

https://nulpointerexception.com/2019/05/05/a-beginner-guide-to-decorator-pattern/

HV
sumber
0

Pola Desain Penghias : Pola ini membantu memodifikasi karakteristik suatu objek saat runtime. Ini memberikan rasa yang berbeda untuk suatu objek dan memberikan fleksibilitas untuk memilih bahan apa yang ingin kita gunakan dalam rasa itu.

Contoh Kehidupan Nyata: Katakanlah Anda memiliki kursi kabin utama dalam penerbangan. Sekarang Anda diperbolehkan memilih beberapa fasilitas dengan tempat duduk. Setiap kemudahan memiliki biaya sendiri yang terkait dengannya. Sekarang jika pengguna memilih Wifi dan makanan premium, ia akan dikenakan biaya untuk kursi + wifi + makanan premium.

masukkan deskripsi gambar di sini

Dalam hal ini pola desain dekorator dapat sangat membantu kami. Kunjungi tautan di atas untuk memahami lebih lanjut tentang pola dekorator dan penerapan satu contoh kehidupan nyata.

Ajit Singh
sumber