The story of ramen
Ramen restaurants sell ramen. The ramen is divided into small bowls and large bowls. A small bowl is 6 yuan, and a large bowl is 6 yuan. 9 yuan. In addition, if you add beef, you need to add 6 yuan, an egg is 1 yuan, a large steak is 5 yuan, and a piece of crispy rice is 1 yuan. If you use the traditional writing method to set ramen noodles with different prices, you need to write 8 categories (number of ramen portions * number of side dishes). If the noodle shop now introduces a new portion size - medium bowl, then 4 new categories need to be added. This will cause a problem - class explosion.
If you have read my previous articlehttps://www.php.cn/php-weizijiaocheng-457250.html, after understanding the bridge mode, you will feel that this problem can be used Bridge mode to solve. Divide it into two broad categories, noodles and side dishes.
Below we use bridge mode to complete the above problems. The code is as follows:
interface INoodle { function cost (); function desc (); } class BigNoodle implements INoodle { private $cost = 9.0; private $dish = null; public function __construct(IDish $dish) { $this->dish = $dish; } public function cost() { return $this->cost + $this->dish->cost(); } public function desc() { return $this->dish->desc() . '大碗拉面'; } } class SmallNoodle implements INoodle { private $cost = 6.0; private $dish = null; public function __construct(IDish $dish) { $this->dish = $dish; } public function cost() { return $this->cost + $this->dish->cost(); } public function desc() { return $this->dish->desc() . '小碗拉面'; } } interface IDish { function cost (); function desc (); } class Beef implements IDish { public function cost () { return 6; } public function desc() { return '牛肉'; } } class Crust implements IDish { public function cost () { return 1; } public function desc() { return '锅巴'; } } class Egg implements IDish { public function cost () { return 1; } public function desc() { return '鸡蛋'; } }
Decorator mode
Use bridge mode It does solve the quasi-explosion problem, but you also know that when we go to eat noodles, sometimes we don’t need side dishes, just noodles, or we need multiple side dishes. For example, I want a large bowl of beef ramen and add 3 pieces of crispy rice noodles. and 2 eggs. For this requirement, the bridge mode cannot be used. To solve this problem, we can use another structural design pattern - the decorator pattern.
Decoration pattern is a structural design pattern that allows you to bind new behaviors to the original object by placing the object into a special encapsulation object that contains the behavior.
To understand the decorator pattern, you can imagine a doll-matryoshka doll
Each set of dolls is equivalent to adding a doll Decorative object. At runtime, the outermost decorative object (take the outer layer) will be run, and then run layer by layer. You may not understand what it means now, but you may understand it if you read this sentence again after reading the following content.
I drew a UML class diagram myself, it’s a bit ugly, everyone will just click on it
Code implementation
abstract class Noodles { abstract function cost (); abstract function desc (); } class BigNoodle extends Noodles { private $cost = 9.0; public function cost() { return $this->cost; } public function desc() { return '大碗拉面'; } } class SmallNoodle extends Noodles { private $cost = 6.0; public function cost() { return $this->cost; } public function desc() { return '小碗拉面'; } } abstract class NoodlesDecorator extends Noodles { } class Beef extends NoodlesDecorator { private $desc = '牛肉'; private $cost = 6.0; protected $noodles = null; public function __construct(Noodles $noodels) { $this->noodles = $noodels; } public function cost () { return $this->cost + $this->noodles->cost(); } public function desc () { return $this->desc . $this->noodles->desc(); } } // egg、curst类代码省略,除了属性值不一样基本和Beef一致
The test code is as follows
$noodles = new BigNoodle(); $beefBigNoodles = new Beef($noodles); $eggBeffBigNoodles = new Egg($beefBigNoodles); echo $eggBeffBigNoodles->desc(); echo $eggBeffBigNoodles->cost() . '元';
Result output: Large bowl of egg and beef ramen 16 yuan
Summary
Thinking about a question, why is the amount of ramen not used as a decorator object here? Think about it, would you order a large bowl and a small bowl of ramen?
Decorator pattern features
The decorator and the decorated object have the same supertype
You can wrap an object with one or more decorators
The object can be decorated at any time, so you can use your favorite decorators dynamically and unlimitedly at runtime to decorate objects.
The above is the detailed content of What is the decorator pattern and how is it different from the bridge pattern?. For more information, please follow other related articles on the PHP Chinese website!