設計模式不得不知道的 UML 類圖

Neilyozの魚不浪發表於2020-04-17

前言

碼字不易,希望大家多提寶貴意見。
我們要給別人講解一個問題的時候,最直觀的方法莫過於用圖形的方式去講解,而不是枯燥的文字。畢竟我們還是個孩子的時候,圖畫更能給我們帶來觸動,而文字我們因為一些認知的問題會導致一些理解能力上的偏差。設計模式裡面的UML類圖就是可以讓你給別人講解設計理念的時候,不用再是枯燥的程式碼和文字,而是直接給別人用類圖的形式來表達的一種方式。

為了方便大家瞭解,我會給出對應的類圖,以及對應的程式碼實現,讓大家有個初步的概念,方便大家來學習設計模式這枯燥的東西。

我們常見的幾種關係:泛化(Generalization)、實現(Realization)、關聯(Association)、聚合(Aggregation)、組合(Composition),依賴(Dependency)。

繼承的類圖

繼承是我們在OOP中最常見的一種方式,讓我們可以節約了不少的開發時間。繼承也有一些別的文字描述方式:泛化。它是一種特殊的依賴。

繼承就是指一個子類繼承了另外一個的功能,並且可以增加它自己的新功能的能力。

表示方法:

​ 繼承使用空心箭頭 + 實線表示。

示例:

設計模式之 UML 類圖

<?php
declare(strict_types=1);

namespace Neilyoz\Example;

abstract class BaseExample {
    public abstract function method01();
    public abstract function method02();
}

class ExtendsExample extends BaseExample
{
    public function method01()
    {
        // TODO: Implement method01() method.
    }

    public function method02()
    {
        // TODO: Implement method02() method.
    }

    public function method03()
    {

    }
}

實現的型別圖

實現表示一個類(class)實現interface介面(可以實現多個介面)的功能。

表示方法:

​ 使用空心三角形 + 虛線表示

示例:

我們都用過相機,有的相機只是可以拍照,但是有的相機例如拍立得,不僅可以拍照還能夠列印出照片。

設計模式之UML類圖
程式碼實現:

<?php

namespace Neilyoz\Example;

interface Camera
{
    public function photograph();
}

interface Printer
{
    public function printer();
}

class Polaroid implements Camera, Printer
{
    public function photograph()
    {
        echo "拍照" . PHP_EOL;
    }

    public function printer()
    {
        echo "沖洗照片" . PHP_EOL;
    }
}

依賴的類圖

介紹:

對於兩個相對獨立的物件,當一個物件負責構造另一個物件的例項,或者依賴另一個物件的服務時,這兩個物件之間主要體現為依賴關係。

使用依賴的類作為引數傳入到對應方法中即可。

表示方法:

​ 依賴關係用 虛線箭頭 表示

示例:

人不管離不開空氣和水對吧,我們依賴這兩個東西生存,我們可以用類圖來描述下。

設計模式之UML類圖

程式碼例項:

<?php
declare(strict_types=1);

namespace Neilyoz\Example;

class Oxygen
{
}

class Water
{
}

class Person
{
    public function metabolism(Oxygen $oxygen, Water $water)
    {
        // 使用 氧氣 水代謝
    }
}

關聯的類圖

對於兩個相對獨立的物件,當一個物件的例項與另一個物件的一些特定例項存在固定的對應關係時,這兩個物件之間為關聯關係。

表示方法:

​ 關聯關係用實現箭頭表示。

示例:

我們的農作物的成熟和天氣氣候有關係,當一個類需要知道另一個類時,可以用關聯。

設計模式之UML類圖

<?php
declare(strict_types=1);

class Climatic
{
    public function getCondition()
    {
        return "秋天";
    }
}

class Cropper
{
    private Climatic $climaticConditions;

    public function __construct(Climatic $climatic)
    {
        $this->climaticConditions = $climatic;
    }

    public function mature()
    {
        if ($this->climaticConditions->getCondition() === "秋天") {
            echo "成熟了" . PHP_EOL;
            return;
        }

        echo "再等等" . PHP_EOL;
    }
}

聚合的類圖

表示一種弱的”擁有”關係,即 has-a 關係,體現的是 A 物件可以包含 B 物件,但 B 物件不是 A 物件的一部分(可有可無的那種)。兩個物件具有各自的生命週期。

表示方法:

​ 聚合關係用 空心菱形 + 實線箭頭 表示

示例:

大家都是人,是人就要混圈子,人的生命週期和圈子的生命是不一樣的,有的人活100多歲,有的圈子沒多久也會解散,但是圈子解散不影響人的生命。

設計模式之UML類圖

<?php
declare(strict_types=1);

namespace Neilyoz\Example;

class Person
{
    private float $money;

    public function collectMoney(float $money)
    {
        $this->money += $money;
    }
}

class Group
{
    private array $members = [];

    public function addMember(Person $person)
    {
        $this->members[] = $person;
    }

    // 分錢
    public function cents()
    {
        array_map(function ($person) {
            $person->collectMoney(rand(0, 100));
        }, $this->members);
    }
}

組合的類圖

組合是一種強的‘擁有’關係,是一種contains-a的關係,體現了嚴格的部分和整體關係,部分和整體的生命週期一樣。

表示方法:

​ 組合關係用 實心的菱形+實線箭頭 表示,還可以使用連線兩端的數字表示某一端有幾個例項。

示例:

設計模式之 UML 類圖

一個男人必須有個大頭還必須有個小頭才能算完整吧。這種就提現了我們的強擁有關係。

<?php
declare(strict_types=1);

class BigHead
{
}

class SmallHead
{

}

class Man
{
    private BigHead $bigHead;
    private SmallHead $smallHead;

    public function __construct()
    {
        // 程式碼中這裡是我們固定不可替換的
        $this->bigHead = new BigHead();
        $this->smallHead = new SmallHead();
    }
}

總結

其實UML類圖的形式複雜起來也很複雜,但是有這些基礎的構圖,我們無非就是搭積木而已。Peace!!!

原文地址

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章