简介
享元模式更常见的叫法是缓存或 cache,一个对象只创建一次,之后一直复用这一对象。
跟单例不同在于,单例是全局只有唯一一个对象,所有人一起用同一个对象,且该对象是提前预设好的,不能定制。
而享元则可以根据参数不同创建出不同的实例,不过实例一旦创建就只保留一份,之后再次创建相同参数的实例则返回该对象,供所有引用的地方使用,引用方之间共享同一份享元实例的数据。
过程有点像定制化的单例模式。
角色
-
Flyweight 享元类
定制化的业务实体,根据不同需要可能定制不同的享元类,但一旦创建出一个享元类,以后都复用这一个类
-
FlyweightFactory 享元工厂类
用来创建和缓存享元实体的地方
类图
代码
class Flyweight
{
private $sharedState;
public function __construct($sharedState)
{
$this->sharedState = $sharedState;
}
public function operation($uniqueState): void
{
$s = json_encode($this->sharedState);
$u = json_encode($uniqueState);
echo "Flyweight: Displaying shared ($s) and unique ($u) state.\n";
}
}
class FlyweightFactory
{
private $flyweights = [];
public function __construct(array $initialFlyweights)
{
foreach ($initialFlyweights as $state) {
$this->flyweights[$this->getKey($state)] = new Flyweight($state);
}
}
private function getKey(array $state): string
{
ksort($state);
return implode("_", $state);
}
public function getFlyweight(array $sharedState): Flyweight
{
$key = $this->getKey($sharedState);
if (!isset($this->flyweights[$key])) {
echo "FlyweightFactory: Can't find a flyweight, creating new one.\n";
$this->flyweights[$key] = new Flyweight($sharedState);
} else {
echo "FlyweightFactory: Reusing existing flyweight.\n";
}
return $this->flyweights[$key];
}
public function listFlyweights(): void
{
$count = count($this->flyweights);
echo "\nFlyweightFactory: I have $count flyweights:\n";
foreach ($this->flyweights as $key => $flyweight) {
echo $key . "\n";
}
}
}
$factory = new FlyweightFactory([
["Chevrolet", "Camaro2018", "pink"],
["Mercedes Benz", "C300", "black"],
["Mercedes Benz", "C500", "red"],
["BMW", "M5", "red"],
["BMW", "X6", "white"],
]);
$factory->listFlyweights();
function addCarToPoliceDatabase(
FlyweightFactory $ff, $plates, $owner,
$brand, $model, $color
) {
echo "\nClient: Adding a car to database.\n";
$flyweight = $ff->getFlyweight([$brand, $model, $color]);
$flyweight->operation([$plates, $owner]);
}
addCarToPoliceDatabase($factory,
"CL234IR",
"James Doe",
"BMW",
"M5",
"red"
);
addCarToPoliceDatabase($factory,
"CL234IR",
"James Doe",
"BMW",
"X1",
"red"
);
$factory->listFlyweights();
output:
FlyweightFactory: I have 5 flyweights:
Chevrolet_Camaro2018_pink
Mercedes Benz_C300_black
Mercedes Benz_C500_red
BMW_M5_red
BMW_X6_white
Client: Adding a car to database.
FlyweightFactory: Reusing existing flyweight.
Flyweight: Displaying shared (["BMW","M5","red"]) and unique (["CL234IR","James Doe"]) state.
Client: Adding a car to database.
FlyweightFactory: Can't find a flyweight, creating new one.
Flyweight: Displaying shared (["BMW","X1","red"]) and unique (["CL234IR","James Doe"]) state.
FlyweightFactory: I have 6 flyweights:
Chevrolet_Camaro2018_pink
Mercedes Benz_C300_black
Mercedes Benz_C500_red
BMW_M5_red
BMW_X6_white
BMW_X1_red
Top comments (0)