-
Notifications
You must be signed in to change notification settings - Fork 2
/
Flyweight.php
105 lines (90 loc) · 2.79 KB
/
Flyweight.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
<?php
namespace DesignPatterns\Structural;
/**
* Simple shopping cart.
*
* Pay your attention that some product data (brand & brandLogo)
* may be duplicated for multiple products. It can leads to inefficient memory usage,
* so we transfer duplicate product data into one single object and refer to it
* from a individual product.
*/
class ShoppingCart
{
/** @var Product[] */
protected $products = [];
public function addProduct($title, $price, $brandName, $brandLogo)
{
$this->products[] = ProductFactory::getProduct($title, $price, $brandName, $brandLogo);
}
public function getProducts()
{
return $this->products;
}
}
/**
* Contains main part of product state,
* brandName and brandLogo will be shared between many products
*/
class Product
{
protected $title;
protected $price;
/** @var ProductBrand */
protected $brand;
public function __construct($title, $price, ProductBrand $brand)
{
$this->title = $title;
$this->price = $price;
$this->brand = $brand;
}
}
/**
* This Flyweight class contains a portion of a state of a product.
*/
class ProductBrand
{
private $brandName;
private $brandLogo;
public function __construct($brandName, $brandLogo)
{
$this->brandName = $brandName;
$this->brandLogo = $brandLogo;
}
}
/**
* Factory decides when to create a new object,
* and when it is possible to do with the existing one.
* It saves memory (especially when we need to store
* a large list of products in memory)
*/
class ProductFactory
{
public static $brandTypes = [];
/**
* Returns new Product instance
*/
public static function getProduct($title, $price, $brandName, $brandLogo): Product
{
$brand = static::getBrand($brandName, $brandLogo);
return new Product($title, $price, $brand);
}
/**
* Checks if we already have brand instance or create a new one if not
*/
protected static function getBrand($brandName, $brandLogo): ProductBrand
{
if (isset(static::$brandTypes[$brandName])) {
return static::$brandTypes[$brandName];
}
return static::$brandTypes[$brandName] = new ProductBrand($brandName, $brandLogo);
}
}
# Client code example
$shoppingCart = new ShoppingCart();
$shoppingCart->addProduct('Sports shoes', 120, 'Nike', 'Nike.png');
$shoppingCart->addProduct('Kids shoes', 100, 'Nike', 'Nike.png');
$shoppingCart->addProduct('Women shoes', 110, 'Nike', 'Nike.png');
$shoppingCart->addProduct('Running shoes', 140, 'Asics', 'Asics.jpg');
$shoppingCart->addProduct('Everyday shoes', 90, 'Adidas', 'Adidas.svg');
echo count($shoppingCart->getProducts()); // 5 products in basket
echo count(ProductFactory::$brandTypes); // and only 3 unique brands instances in memory