热门问题
时间线
聊天
视角
合成模式
来自维基百科,自由的百科全书
Remove ads
在軟件工程中,合成模式,也翻譯為組成模式,是一種設計模式。合成(composite)模式描述了一組對象,按照對待相同對象類型的一個單一實例的方式處置它們。合成模式的意圖是將諸多對象合成(compose)入表示部份-整體層級的樹結構之中。實現合成模式使得客戶能統一的處置單獨對象和合成對象[1]。

結構

- 客戶
Client
類不直接(單獨的)提及Leaf
和Composite
類,Client
轉而提及公共的構件Component
接口,並且統一的處置Leaf
和Composite
。 - 葉子
Leaf
類沒有子對象並且直接實現Component
接口。 - 合成
Composite
類維護Component
對象(children
)的一個容器,並且將請求轉發到這些children
(for each child in children: child.operation()
)。
對象圖展示運行時交互:在這個例子中,客戶Client
對象發送請求到樹結構的頂層合成Composite
對象(具有類型 Component
) 。這個請求被沿着樹結構轉發到(辦理於)所有的子Component
對象(Leaf
和Composite
對象)。

示例
下面的例子是基於《設計模式》書中先於C++98的樣例代碼的C++23實現。
import std;
using Currency = double;
template <typename T>
using LinkedList = std::list<T>;
// declares the interface for objects in the composition.
class Equipment { // Component
private:
std::string name;
Currency netPrice;
protected:
Equipment() = default;
Equipment(const String& name):
name{name}, netPrice{0} {}
public:
// implements default behavior for the interface common to all classes, as appropriate.
[[nodiscard]]
virtual const std::string& getName() const noexcept {
return name;
}
virtual void setName(const std::string& name_) noexcept {
name = name_;
}
[[nodiscard]]
virtual Currency getNetPrice() const noexcept {
return netPrice;
}
virtual void setNetPrice(Currency netPrice_) noexcept {
netPrice = netPrice_;
}
// declares an interface for accessing and managing its child components.
virtual void add(std::shared_ptr<Equipment>) = 0;
virtual void remove(std::shared_ptr<Equipment>) = 0;
virtual ~Equipment() = default;
};
// defines behavior for components having children.
class CompositeEquipment : public Equipment { // Composite
private:
// stores child components.
LinkedList<std::shared_ptr<Equipment>> equipment;
protected:
CompositeEquipment() = default;
CompositeEquipment(const std::string& name):
Equipment(name), equipment{} {}
public:
// implements child-related operations in the Component interface.
[[nodiscard]]
virtual Currency getNetPrice() const noexcept override {
Currency total = Equipment::getNetPrice();
for (const Equipment& i: equipment) {
total += i->getNetPrice();
}
return total;
}
virtual void add(std::shared_ptr<Equipment> equipment_) override {
equipment.push_front(equipment_.get());
}
virtual void remove(std::shared_ptr<Equipment> equipment_) override {
equipment.remove(equipment_.get());
}
};
// represents leaf objects in the composition.
class FloppyDisk : public Equipment { // Leaf
public:
FloppyDisk(const std::string& name_):
Equipment(name) {}
// A leaf has no children.
void add(std::shared_ptr<Equipment>) override {
throw std::runtime_error("FloppyDisk::add() cannot be called!");
}
void remove(std::shared_ptr<Equipment>) override {
throw std::runtime_error("FloppyDisk::remove() cannot be called!");
}
};
class Chassis : public CompositeEquipment {
public:
Chassis(const std::string& name):
CompositeEquipment(name) {}
};
int main() {
// The smart pointers prevent memory leaks.
std::shared_ptr<FloppyDisk> fd1 = std::make_shared<FloppyDisk>("3.5in Floppy");
fd1->setNetPrice(19.99);
std::println("{}: netPrice = {}", fd1->getName(), fd1->getNetPrice);
std::shared_ptr<FloppyDisk> fd2 = std::make_shared<FloppyDisk>("5.25in Floppy");
fd2->setNetPrice(29.99);
std::println("{}: netPrice = {}", fd2->getName(), fd2->getNetPrice);
std::unique_ptr<Chassis> ch = std::make_unique<Chassis>("PC Chassis");
ch->setNetPrice(39.99);
ch->add(fd1);
ch->add(fd2);
std::println("{}: netPrice = {}", ch->getName(), ch->getNetPrice);
fd2->add(fd1);
}
程序的輸出為:
3.5in Floppy: netPrice=19.99
5.25in Floppy: netPrice=29.99
PC Chassis: netPrice=89.97
terminate called after throwing an instance of 'std::runtime_error'
what(): FloppyDisk::add
Remove ads
下面是Python的例子:
class Equipment():
def __init__(self, name, netprice=None, **kwargs):
self.name = name
self.netprice = netprice
for key, value in kwargs.items():
self.__dict__[key] = value
def get_name(self):
return self.name
def set_netprice(self, netprice):
self.netprice = netprice
def get_netprice(self):
return self.netprice
class CompositeEquipment(Equipment):
def __init__(self, *args, **kwargs):
self.linked_list = []
super().__init__(*args, **kwargs)
def add(self, equipment):
self.linked_list.insert(0, equipment)
def remove(self, equipment):
self.linked_list.remove(equipment)
def get_netprice(self):
total = (0 if self.netprice is None
else self.netprice)
for i in self.linked_list:
total += i.get_netprice()
return total
class ComputerCase(CompositeEquipment): pass
class Chassis(Equipment): pass
class Motherboard(CompositeEquipment): pass
class CPU(Equipment): pass
class RAM(Equipment): pass
class HardDisk(Equipment): pass
def demo():
cpu = CPU("Intel CPU", 200)
ram = RAM("DDR4", 150)
hd = HardDisk("SSD", 250)
board = Motherboard("MSI board", 180)
board.add(cpu)
board.add(ram)
board.add(hd)
chassis = Chassis("ATX", 50)
pc_case = ComputerCase("an assembled computer")
pc_case.add(board)
pc_case.add(chassis)
print(f"The net price of {pc_case.get_name()} is {pc_case.get_netprice()}.")
其執行:
>>> demo()
The net price of an assembled computer is 830.
Remove ads
參見
引用
外部連結
Wikiwand - on
Seamless Wikipedia browsing. On steroids.
Remove ads