Sharing meta model of PHP design pattern

Posted by ludachris on Tue, 30 Jun 2020 04:12:16 +0200

The word "Xiang Yuan" has no special meaning in Chinese, so we should divide it into two parts. "Sharing" means sharing, and "Yuan" is elements. In this way, it seems easy to understand that sharing certain elements.

Gof class diagram and its explanation

GoF definition: using sharing technology to support a large number of fine-grained objects effectively

GoF class diagram

code implementation

interface Flyweight
{
    public function operation($extrinsicState) : void;
}

class ConcreteFlyweight implements Flyweight
{
    private $intrinsicState = 101;
    function operation($extrinsicState) : void
    {
        echo 'Shared share object' . ($extrinsicState + $this->intrinsicState) . PHP_EOL;
    }
}

class UnsharedConcreteFlyweight implements Flyweight
{
    private $allState = 1000;
    public function operation($extrinsicState) : void
    {
        echo 'Non shared sharing object:' . ($extrinsicState + $this->allState) . PHP_EOL;
    }
}

Define the shared interface and its implementation. Note that there are two implementations: concreteflyweight shares state, unshared concreteflyweight does not share, or its state does not need to be shared

class FlyweightFactory
{
    private $flyweights = [];

    public function getFlyweight($key) : Flyweight
    {
        if (!array_key_exists($key, $this->flyweights)) {
            $this->flyweights[$key] = new ConcreteFlyweight();
        }
        return $this->flyweights[$key];
    }
}

Save those objects that need to be shared, as a factory to create the shared objects, ensure that there will be only one object under the same key value, saving the cost of creating the same object

$factory = new FlyweightFactory();

$extrinsicState = 100;
$flA = $factory->getFlyweight('a');
$flA->operation(--$extrinsicState);

$flB = $factory->getFlyweight('b');
$flB->operation(--$extrinsicState);

$flC = $factory->getFlyweight('c');
$flC->operation(--$extrinsicState);

$flD = new UnsharedConcreteFlyweight();
$flD->operation(--$extrinsicState);

The external state $extransicstate can be shared among various objects by the client

  • It's interesting. This pattern has a lot of code
  • When an application uses a large number of very similar objects, and most of the state of the object can be changed to external state, it is suitable for sharing meta pattern
  • The factory here stores the list of objects. It does not create objects like factory methods or abstract factories. Although it is also created here, if the object exists, it will be returned directly, and the list is always maintained
  • In reality, everyone must have used the sharing mode. Various pooling technologies are typical applications: thread pool, connection pool, etc. the other two same String types can be = = = in php or Java. This is also applied to the share mode. They are the same memory address. This is not a kind of sharing
  • There is an extremely classic example about the Xiangyuan mode, which is much better than my following example, that is, the chessboard of go. Go is only black and white, so two objects are enough. What's next? Just change their position and state! Interested friends can search ha!
  • The IoC container in Laravel can be regarded as an implementation of sharing element pattern. It saves the object in the array and uses it through the closure mechanism when necessary. Some classes share some state properties. You can look at the code to understand.

When it comes to technology, it's about changing shells. After all, people still like the color of mobile phones to show their personality. As I said before, if we have to make a production line for each color, it will not be a huge investment. Fortunately, our factory (Xiangyuan factory) only produces the most basic background shell (object) for each model, and then color it through a special printing line (state change)! Well, the next Iphone will imitate us sooner or later. It seems that we have to put together all kinds of gold and all kinds of local tyrants. Maybe we can call the dragon!!

Complete code: https://github.com/zhangyue0503/designpatterns-php/blob/master/13.flyweights/source/flyweights.php

example

As expected, we still send short messages. This time, we still use Alibaba cloud and Aurora SMS to send messages. However, this time, we use the Heyuan mode to achieve this. In the Xiangyuan factory, we keep two different types of objects. Let's make them changeable through internal and external states!

SMS sending class diagram

Complete source code: https://github.com/zhangyue0503/designpatterns-php/blob/master/13.flyweights/source/flyweights-message.php

<?php

interface Message
{
    public function send(User $user);
}

class AliYunMessage implements Message
{
    private $template;
    public function __construct($template)
    {
        $this->template = $template;
    }
    public function send(User $user)
    {
        echo 'Using alicloud SMS to' . $user->GetName() . 'send out:';
        echo $this->template->GetTemplate(), PHP_EOL;
    }
}

class JiGuangMessage implements Message
{
    private $template;
    public function __construct($template)
    {
        $this->template = $template;
    }
    public function send(User $user)
    {
        echo 'Use Aurora SMS to' . $user->GetName() . 'send out:';
        echo $this->template->GetTemplate(), PHP_EOL;
    }
}

class MessageFactory
{
    private $messages = [];
    public function GetMessage(Template $template, $type = 'ali')
    {
        $key = md5($template->GetTemplate() . $type);
        if (!key_exists($key, $this->messages)) {
            if ($type == 'ali') {
                $this->messages[$key] = new AliYunMessage($template);
            } else {
                $this->messages[$key] = new JiGuangMessage($template);
            }
        }
        return $this->messages[$key];
    }

    public function GetMessageCount()
    {
        echo count($this->messages);
    }
}

class User
{
    public $name;
    public function GetName()
    {
        return $this->name;
    }
}

class Template
{
    public $template;
    public function GetTemplate()
    {
        return $this->template;
    }
}

// Internal state
$t1 = new Template();
$t1->template = 'Template 1, not bad!';

$t2 = new Template();
$t2->template = 'Template 2, OK!';

// External state
$u1 = new User();
$u1->name = 'Zhang San';

$u2 = new User();
$u2->name = 'Li Si';

$u3 = new User();
$u3->name = 'Wang Wu';

$u4 = new User();
$u4->name = 'Zhao Liu';

$u5 = new User();
$u5->name = 'pseudo-ginseng';

// Xiangyuan factory
$factory = new MessageFactory();

// Sent by alicloud
$m1 = $factory->GetMessage($t1);
$m1->send($u1);

$m2 = $factory->GetMessage($t1);
$m2->send($u2);

echo $factory->GetMessageCount(), PHP_EOL; // 1

$m3 = $factory->GetMessage($t2);
$m3->send($u2);

$m4 = $factory->GetMessage($t2);
$m4->send($u3);

echo $factory->GetMessageCount(), PHP_EOL; // 2

$m5 = $factory->GetMessage($t1);
$m5->send($u4);

$m6 = $factory->GetMessage($t2);
$m6->send($u5);

echo $factory->GetMessageCount(), PHP_EOL; // 2

// Add Aurora
$m1 = $factory->GetMessage($t1, 'jg');
$m1->send($u1);

$m2 = $factory->GetMessage($t1);
$m2->send($u2);

echo $factory->GetMessageCount(), PHP_EOL; // 3

$m3 = $factory->GetMessage($t2);
$m3->send($u2);

$m4 = $factory->GetMessage($t2, 'jg');
$m4->send($u3);

echo $factory->GetMessageCount(), PHP_EOL; // 4

$m5 = $factory->GetMessage($t1, 'jg');
$m5->send($u4);

$m6 = $factory->GetMessage($t2, 'jg');
$m6->send($u5);

echo $factory->GetMessageCount(), PHP_EOL; // 4


explain

  • There is a little bit of code, but actually there are two types of classes, which generate four kinds of objects. Here, different objects of each class are distinguished according to the template
  • This kind of combination is more convenient, and then combine with other modes to optimize the factory here. Well, the future is limitless. You can think about it!
  • Sharing element mode is suitable for scenarios where there are a large number of similar objects and need buffer pool in the system. It can reduce the memory consumption and improve the efficiency, but it will increase the complexity and need to share the internal and external states
  • The most important feature is that there is a unique identifier. When the object is already in memory, the object is returned directly without creating it

What to watch in the next period

The example of sharing pattern is far fetched, but it is true that this kind of design pattern is not used much in our daily development, on the other hand, the typical examples are too classic. Anyway, just remember its characteristics. It is not allowed to write the code in the application. When you look back, you will find that this is not the sharing pattern I have learned! Well, in the next chapter, we'll learn about a less used and more complex model, but maybe you can see it often! Combination mode

===============

Official account: hard core project manager

Add wechat / QQ friends: [DarkMatterZyCoder/149844827] get free PHP and project management learning materials

Topics: PHP github Java Laravel