ผมได้รับการศึกษาแบบมัณฑนากรเป็นเอกสารในการขาด
โปรดช่วยผมเข้าใจแบบมัณฑนากร ใครช่วยยกตัวอย่างการใช้กรณีที่มีประโยชน์ในโลกแห่งความจริง?
ผมได้รับการศึกษาแบบมัณฑนากรเป็นเอกสารในการขาด
โปรดช่วยผมเข้าใจแบบมัณฑนากร ใครช่วยยกตัวอย่างการใช้กรณีที่มีประโยชน์ในโลกแห่งความจริง?
คำตอบ:
รูปแบบมัณฑนากรบรรลุเป้าหมายเดียวของการเพิ่มความรับผิดชอบให้กับวัตถุใด ๆ แบบไดนามิก
พิจารณากรณีของร้านพิซซ่า ในร้านพิซซ่าพวกเขาจะขายพิซซ่าไม่กี่สายพันธุ์และพวกเขายังมีรสชาติในเมนู ตอนนี้ลองนึกภาพสถานการณ์ที่ร้านพิซซ่าต้องระบุราคาสำหรับการรวมกันของพิซซ่าและท็อปปิ้ง แม้ว่าจะมีพิซซ่าขั้นพื้นฐานสี่ตัวและท็อปปิ้ง 8 ชนิดที่แตกต่างกันแอปพลิเคชั่นจะบ้าคลั่งที่จะรักษาส่วนผสมที่เป็นรูปธรรมเหล่านี้ของพิซซ่าและท็อปปิ้ง
ที่นี่รูปแบบมัณฑนากรมา
ตามรูปแบบของมัณฑนากรคุณจะใช้ท็อปปิ้งเป็นมัณฑนากรและพิซซ่าจะได้รับการตกแต่งโดยมัณฑนากรของท็อปปิ้ง ในทางปฏิบัติลูกค้าแต่ละรายต้องการรสชาติที่ต้องการและยอดเรียกเก็บเงินสุดท้ายของเขาจะประกอบด้วยพิซซ่าฐานและท็อปปิ้งคำสั่งเพิ่มเติม นักตกแต่งหน้าเครื่องประดับแต่ละคนจะรู้เกี่ยวกับพิซซ่าว่ามันเป็นของตกแต่งและราคา GetPrice () วิธีการติดตามวัตถุจะคืนราคาสะสมของทั้งพิซซ่าและท็อปปิ้ง
นี่คือตัวอย่างรหัสของคำอธิบายด้านบน
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;
}
}
นี่เป็นตัวอย่างง่ายๆของการเพิ่มพฤติกรรมใหม่ให้กับวัตถุที่มีอยู่แบบไดนามิกหรือรูปแบบมัณฑนากร เนื่องจากลักษณะของภาษาแบบไดนามิกเช่น Javascript รูปแบบนี้กลายเป็นส่วนหนึ่งของภาษาเอง
// 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');
switch
หรือแบบธรรมดาif
คุณจะสามารถอ้างได้ว่านี่เป็นตัวอย่างที่ดีของการเพิ่มพฤติกรรมให้กับคลาส แต่เราต้องการอย่างน้อยสองคลาสเพื่อกำหนดมัณฑนากรและวัตถุตกแต่งในรูปแบบนี้
เป็นที่น่าสังเกตว่าโมเดล Java i / o นั้นเป็นไปตามรูปแบบของมัณฑนากร เลเยอร์ของผู้อ่านนี้อยู่ด้านบนของผู้อ่านที่อยู่ด้านบนของ ... เป็นตัวอย่างที่แท้จริงของมัณฑนากร
ตัวอย่าง - สถานการณ์สมมติว่าคุณกำลังเขียนโมดูลการเข้ารหัส การเข้ารหัสนี้สามารถเข้ารหัสไฟล์ที่ชัดเจนโดยใช้ DES - มาตรฐานการเข้ารหัสข้อมูล ในทำนองเดียวกันในระบบคุณสามารถมีการเข้ารหัสเป็น AES - มาตรฐานการเข้ารหัสขั้นสูง นอกจากนี้คุณสามารถมีการรวมกันของการเข้ารหัส - แรก DES แล้ว AES หรือคุณสามารถมี AES ก่อนจากนั้นก็ DES
การสนทนา - คุณจะรับมือสถานการณ์นี้อย่างไร คุณไม่สามารถสร้างวัตถุของชุดค่าผสมดังกล่าว - เช่น - AES และ DES - รวม 4 ชุด ดังนั้นคุณต้องมีวัตถุ 4 ชิ้นสิ่งนี้จะซับซ้อนเนื่องจากประเภทการเข้ารหัสจะเพิ่มขึ้น
วิธีแก้ไข - สร้างสแต็คต่อไป - รวมกันตามความต้องการ - ณ เวลาทำงาน ข้อดีอีกประการของแนวทางสแต็กนี้คือคุณสามารถผ่อนคลายได้อย่างง่ายดาย
นี่คือวิธีแก้ปัญหา - ใน C ++
ประการแรกคุณต้องมีคลาสพื้นฐาน - หน่วยพื้นฐานของสแต็ก คุณคิดว่าเป็นฐานของกองซ้อน ในตัวอย่างนี้มันเป็นไฟล์ที่ชัดเจน มาติดตามความแตกต่างกันเสมอ กำหนดให้เป็นคลาสอินเตอร์เฟสของหน่วยพื้นฐานนี้ ด้วยวิธีนี้คุณสามารถใช้งานได้ตามที่คุณต้องการ นอกจากนี้คุณไม่จำเป็นต้องคิดถึงการพึ่งพาในขณะที่รวมหน่วยพื้นฐานนี้
นี่คือคลาสอินเตอร์เฟส -
class IclearData
{
public:
virtual std::string getData() = 0;
virtual ~IclearData() = 0;
};
IclearData::~IclearData()
{
std::cout<<"Destructor called of IclearData"<<std::endl;
}
ตอนนี้ใช้คลาสอินเทอร์เฟซนี้ -
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;
}
};
ทีนี้มาสร้างคลาสนามธรรมของมัณฑนากรซึ่งสามารถขยายเพื่อสร้างรสชาติได้ทุกชนิด - ที่นี่รสชาติคือประเภทการเข้ารหัส คลาสนามธรรมมัณฑนากรนี้เกี่ยวข้องกับคลาสพื้นฐาน ดังนั้นมัณฑนากร "เป็น" ประเภทคลาสอินเตอร์เฟส ดังนั้นคุณต้องใช้การสืบทอด
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;
}
ทีนี้มาสร้างคลาสมัณฑนากรคอนกรีต - ประเภทการเข้ารหัส - 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;
}
};
ทีนี้สมมติว่าประเภทมัณฑนากรคือ DES -
const std :: string desEncrypt = "DES เข้ารหัส";
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;
}
};
มาสร้างรหัสลูกค้าเพื่อใช้คลาสมัณฑนากรนี้ -
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;
}
คุณจะเห็นผลลัพธ์ต่อไปนี้ -
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
นี่คือแผนภาพ UML - คลาสของมัน ในกรณีที่คุณต้องการข้ามรหัสและมุ่งเน้นด้านการออกแบบ
strategy pattern
ใช่หรือไม่
รูปแบบมัณฑนากรช่วยให้คุณเปลี่ยนหรือกำหนดค่าการทำงานของวัตถุของคุณโดยผูกมัดกับคลาสย่อยอื่น ๆ ที่คล้ายกันของวัตถุนี้
ตัวอย่างที่ดีที่สุดคือคลาส InputStream และ OutputStream ในแพ็คเกจ 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.
รูปแบบการออกแบบมัณฑนากรใน Java คืออะไร
คำจำกัดความที่เป็นทางการของรูปแบบมัณฑนากรจากหนังสือ GoF (รูปแบบการออกแบบ: องค์ประกอบของซอฟต์แวร์เชิงวัตถุที่ใช้ซ้ำได้, 1995, Pearson Education, Inc. Publishing เป็น Pearson Addison Wesley) กล่าวว่าคุณทำได้
"แนบความรับผิดชอบเพิ่มเติมไปยังวัตถุแบบไดนามิกผู้ตกแต่งเป็นทางเลือกที่ยืดหยุ่นในการทำคลาสย่อยเพื่อขยายฟังก์ชันการทำงาน"
สมมติว่าเรามีพิซซ่าและเราต้องการตกแต่งด้วยท็อปปิ้งเช่นไก่มาซาลาหัวหอมและมอสซาเรลล่าชีส เรามาดูวิธีการใช้ใน Java ...
โปรแกรมเพื่อสาธิตวิธีการใช้ Decorator Design Pattern ใน Java
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());
}
}
ฉันใช้รูปแบบมัณฑนากรอย่างกว้างขวางในที่ทำงานของฉัน ฉันโพสต์บนบล็อกของฉันเกี่ยวกับวิธีใช้กับการบันทึก
รูปแบบการตกแต่งภายในช่วยให้คุณเพิ่มพฤติกรรมแบบไดนามิกไปยังวัตถุ
ลองมาตัวอย่างที่คุณต้องสร้างแอพที่คำนวณราคาเบอร์เกอร์ประเภทต่างๆ คุณต้องจัดการเบอร์เกอร์หลากหลายรูปแบบเช่น "ใหญ่" หรือ "กับชีส" ซึ่งแต่ละร้านมีราคาที่สัมพันธ์กับเบอร์เกอร์พื้นฐาน เช่นเพิ่ม $ 10 สำหรับเบอร์เกอร์กับชีสเพิ่มอีก $ 15 สำหรับเบอร์เกอร์ขนาดใหญ่ ฯลฯ
ในกรณีนี้คุณอาจถูกล่อลวงให้สร้างคลาสย่อยเพื่อจัดการสิ่งเหล่านี้ เราอาจแสดงสิ่งนี้ใน Ruby เป็น:
class Burger
def price
50
end
end
class BurgerWithCheese < Burger
def price
super + 15
end
end
ในตัวอย่างด้านบนคลาส BurgerWithCheese สืบทอดมาจาก Burger และแทนที่เมธอด price เพื่อเพิ่ม $ 15 เข้ากับราคาที่กำหนดไว้ใน class super คุณจะสร้างคลาส LargeBurger และกำหนดราคาเทียบกับ Burger แต่คุณต้องกำหนดคลาสใหม่สำหรับการรวมกันของ "ใหญ่" และ "กับชีส"
ตอนนี้จะเกิดอะไรขึ้นถ้าเราต้องเสิร์ฟ "เบอร์เกอร์กับมันฝรั่งทอด"? เรามี 4 คลาสเพื่อจัดการชุดค่าผสมเหล่านี้และเราจะต้องเพิ่มอีก 4 ชั้นเพื่อจัดการชุดค่าผสมทั้งหมด 3 รายการ - "ใหญ่", "กับชีส" และ "พร้อมมันฝรั่งทอด" เราต้องการ 8 คลาสตอนนี้ เพิ่มสถานที่ให้บริการอื่นและเราจะต้อง 16 นี้จะเติบโตเป็น 2 ^ n
ให้ลองกำหนด BurgerDecorator ที่ใช้ในวัตถุ 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
ในตัวอย่างด้านบนเราได้สร้างคลาส BurgerDecorator ซึ่งคลาส BurgerWithCheese สืบทอดมา นอกจากนี้เรายังสามารถแสดงรูปแบบ "ใหญ่" โดยการสร้างคลาส LargeBurger ตอนนี้เราสามารถกำหนดเบอร์เกอร์ขนาดใหญ่กับชีสที่รันไทม์เป็น:
b = LargeBurger.new(cheese_burger)
b.price # => 50 + 15 + 20 = 85
โปรดจำไว้ว่าการใช้การสืบทอดเพื่อเพิ่มรูปแบบ "with fries" จะเกี่ยวข้องกับการเพิ่มคลาสย่อยอีก 4 รายการอย่างไร ด้วยการตกแต่งเราจะสร้าง BurgerWithFries ใหม่หนึ่งคลาสเพื่อจัดการรูปแบบใหม่และจัดการสิ่งนี้ที่รันไทม์ สถานที่ให้บริการใหม่แต่ละแห่งจะต้องใช้มัณฑนากรเพิ่มเติมเพื่อให้ครอบคลุมการเรียงสับเปลี่ยนทั้งหมด
PS นี่เป็นบทความสั้น ๆ ของบทความที่ฉันเขียนเกี่ยวกับการใช้รูปแบบมัณฑนากรในทับทิมซึ่งคุณสามารถอ่านได้หากคุณต้องการดูตัวอย่างโดยละเอียดเพิ่มเติม
มัณฑนากร:
อ้างถึงsourcemakingบทความสำหรับรายละเอียดเพิ่มเติม
มัณฑนากร (Abstract) : เป็นคลาสนามธรรม / อินเตอร์เฟสซึ่งใช้อินเทอร์เฟซคอมโพเนนต์ มันมีองค์ประกอบอินเตอร์เฟซ หากไม่มีคลาสนี้คุณจำเป็นต้องมีคลาสย่อยของ ConcreteDecorators สำหรับชุดค่าผสมที่แตกต่างกัน องค์ประกอบขององค์ประกอบลดชั้นย่อยที่ไม่จำเป็น
ตัวอย่าง 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);;
}
ดูคำถาม SE ด้านล่างสำหรับแผนภาพ UML และตัวอย่างรหัส
บทความที่มีประโยชน์:
ตัวอย่างคำที่แท้จริงของรูปแบบการตกแต่ง: VendingMachineDecoratorได้รับการอธิบาย @
เมื่อใดที่จะใช้รูปแบบมัณฑนากร?
Beverage beverage = new SugarDecorator(new LemonDecorator(new Tea("Assam Tea")));
beverage.decorateBeverage();
beverage = new SugarDecorator(new LemonDecorator(new Coffee("Cappuccino")));
beverage.decorateBeverage();
ในตัวอย่างด้านบนชาหรือกาแฟ (เครื่องดื่ม) ตกแต่งด้วยน้ำตาลและมะนาว
รูปแบบมัณฑนากรบรรลุวัตถุประสงค์เดียวของแบบไดนามิกเพิ่มความรับผิดชอบต่อวัตถุใด ๆ
Java I / O Modelขึ้นอยู่กับรูปแบบของมัณฑนากร
มีตัวอย่างใน Wikipedia เกี่ยวกับการตกแต่งหน้าต่างด้วยแถบเลื่อน:
http://en.wikipedia.org/wiki/Decorator_pattern
นี่คืออีกตัวอย่าง 'โลกแห่งความจริง' ของ "สมาชิกในทีมหัวหน้าทีมและผู้จัดการ" ซึ่งแสดงให้เห็นว่ารูปแบบมัณฑนากรไม่สามารถถูกแทนที่ด้วยการสืบทอดง่าย ๆ :
https://zishanbilal.wordpress.com/2011/04/28/design-patterns-by-examples-decorator-pattern/
เมื่อสักครู่ที่ฉันได้ปรับเปลี่ยน codebase เป็นรูปแบบการใช้มัณฑนากรดังนั้นฉันจะพยายามอธิบายกรณีการใช้งาน
สมมติว่าเรามีชุดบริการและขึ้นอยู่กับว่าผู้ใช้ได้รับสิทธิ์การใช้งานของบริการเฉพาะเราต้องเริ่มบริการหรือไม่
บริการทั้งหมดมีอินเตอร์เฟซทั่วไป
interface Service {
String serviceId();
void init() throws Exception;
void start() throws Exception;
void stop() throws Exception;
}
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
}
}
ถ้าคุณสังเกตอย่างระมัดระวังจะขึ้นอยู่กับServiceSupport
LicenseManager
แต่ทำไมมันถึงต้องพึ่งพาLicenseManager
? ถ้าเราต้องการบริการพื้นหลังซึ่งไม่จำเป็นต้องตรวจสอบข้อมูลสิทธิ์ใช้งาน ในสถานการณ์ปัจจุบันเราจะต้องฝึกซ้อมLicenseManager
เพื่อกลับtrue
ใช้บริการพื้นหลัง วิธีการนี้ดูเหมือนจะไม่ดีสำหรับฉัน ตามที่ฉันตรวจสอบใบอนุญาตและตรรกะอื่น ๆ มีมุมฉากซึ่งกันและกัน
ดังนั้นรูปแบบของมัณฑนากรจึงมาช่วยและที่นี่จะเริ่มการรีแฟคเตอร์ด้วย TDD
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");
ลองยกตัวอย่าง PubG ปืนไรเฟิลจู่โจมทำงานได้ดีที่สุดเมื่อใช้การซูม 4x และในขณะที่เรากำลังใช้งานอยู่เราจำเป็นต้องมีผู้ชดเชยและผู้ยับยั้ง มันจะลดการหดตัวและลดเสียงการยิงเช่นเดียวกับเสียงก้อง เราจะต้องใช้คุณสมบัตินี้ซึ่งเราจะอนุญาตให้ผู้เล่นซื้อปืนที่ชื่นชอบและอุปกรณ์เสริมของพวกเขา ผู้เล่นสามารถซื้อปืนหรืออุปกรณ์เสริมบางอย่างหรืออุปกรณ์เสริมทั้งหมดและพวกเขาจะถูกเรียกเก็บเงินตามความเหมาะสม
มาดูกันว่ารูปแบบการตกแต่งภายในใช้ที่นี่:
สมมติว่ามีคนต้องการซื้อ SCAR-L พร้อมกับอุปกรณ์เสริมทั้งสามที่กล่าวถึงข้างต้น
สิ่งนี้จะนำไปสู่แผนภาพคลาสเช่นนี้:
ตอนนี้เราสามารถมีคลาสดังนี้:
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());
}
}
เราสามารถเพิ่มอุปกรณ์เสริมอื่น ๆ ในทำนองเดียวกันและตกแต่งปืนของเรา
อ้างอิง:
https://nulpointerexception.com/2019/05/05/a-beginner-guide-to-decorator-pattern/
รูปแบบการออกแบบมัณฑนากร : รูปแบบนี้ช่วยในการปรับเปลี่ยนลักษณะของวัตถุเมื่อรันไทม์ มันให้รสชาติที่แตกต่างกับวัตถุและให้ความยืดหยุ่นในการเลือกส่วนผสมที่เราต้องการใช้ในรสชาตินั้น
ตัวอย่างชีวิตจริง: ให้บอกว่าคุณมีที่นั่งในห้องโดยสารหลักในเที่ยวบิน ตอนนี้คุณได้รับอนุญาตให้เลือกสิ่งอำนวยความสะดวกหลายอย่างพร้อมที่นั่ง สิ่งอำนวยความสะดวกแต่ละอย่างมีค่าใช้จ่ายของตัวเองที่เกี่ยวข้อง ตอนนี้หากผู้ใช้เลือก Wifi และอาหารพรีเมี่ยมเขา / เธอจะถูกเรียกเก็บเงินสำหรับที่นั่ง + wifi + อาหารพรีเมี่ยม
ในกรณีนี้รูปแบบการออกแบบมัณฑนากรสามารถช่วยเราได้จริงๆ เยี่ยมชมลิงค์ด้านบนเพื่อทำความเข้าใจเพิ่มเติมเกี่ยวกับรูปแบบมัณฑนากรและการนำตัวอย่างจริงมาใช้