Mermaid vs PlantUML 类图:正式 UML 为什么默认选 PlantUML

··Updated ·6 min read
mermaidplantumlclass-diagramdiagram-as-codeuml

本文只比较类图表达和长期维护能力,PlantUML 更强,应作为正式 UML 类图的默认选择。 官方资料核验于 2026-07-22;整体工具差异请看系列总览

Mermaid 足以说明常见领域对象、成员和关系;但正式设计资产通常还要承载关联类、明确声明元素、可裁剪视图、细粒度注释和稳定的样式规则。这些场景下,PlantUML 的官方语法覆盖得更完整。

核心结论

  • 两者都能表达常见类关系、可见性、成员、基数和 annotation。
  • Mermaid 官网自 11.15.0 起支持嵌套 namespace;本项目锁定 Mermaid 11.6.0,不能把官网新能力当作当前运行时能力。
  • PlantUML 可直接声明多种元素,并提供 hide/show/remove/restore,适合从同一模型维护不同评审视图。
  • 类图负责对象模型;数据表、键和基数应交给ER 图对比,系统边界与组件关系可结合软件架构图对比阅读。

本文依据以下一手资料:

Mermaid vs PlantUML 类图核心差异

对比点MermaidPlantUML选择建议
类、属性、方法支持支持两者都可以
可见性支持 +-#~支持 +-#~两者都可以
静态/抽象成员支持 $* 标记支持 {static}{abstract} 等更显式写法正式 UML 图 PlantUML 更清楚
继承/实现/组合/聚合/依赖支持常见关系支持常见关系两者都可以
基数支持关系两端标注支持关系两端标注两者都可以
泛型支持 ~T~,但复杂泛型有限制支持泛型表达复杂类型模型 PlantUML 更合适
接口/枚举/抽象类通过 annotation 表达interfaceenumabstract class 等声明元素PlantUML 语义更显式
包和命名空间官网 11.15.0+ 支持嵌套 namespace;项目 11.6.0 不具备此版本能力支持 package、namespace 和多种包样式版本与长期模型都要单独判断
隐藏成员和裁剪视图官方类图页未提供对应裁剪命令支持 hide、show、remove、restore、按标签裁剪设计评审 PlantUML 更合适
注释支持 notenote for支持方向注释、浮动注释、链接注释、字段/方法注释PlantUML 注释能力更细
关联类不突出支持 association class需要严格 UML 语义时选 PlantUML
样式控制支持 classDef、CSS class、主题配置支持 skinparam、颜色、stereotype 样式等统一图形规范 PlantUML 更合适

先给一句话结论:

Mermaid 类图适合把结构讲清楚;PlantUML 类图适合把结构、语义、裁剪视图和输出规范一起控制住。

Mermaid 能覆盖常见类模型吗?

能。Mermaid 官方类图文档列出 8 种关系,并支持 +-#~ 可见性、泛型、annotation、note 和 direction。它能把常见对象模型讲清楚,但这些图形标记不等于对编程语言类型规则的验证。

下面是一个订单领域模型:Order 拥有多个 OrderItem,使用 PaymentMethod 接口完成支付,并和 Customer 建立关联。

Mermaid 代码和图

classDiagram
  direction LR

  class Customer {
    +String id
    +String email
    +placeOrder()
  }

  class Order {
    +String id
    +OrderStatus status
    +Money total
    +addItem(productId, quantity)
    +checkout() PaymentResult
  }

  class OrderItem {
    +String productId
    +int quantity
    +Money price
    +subtotal() Money
  }

  class PaymentMethod {
    <<Interface>>
    +authorize(amount) PaymentResult
  }

  class CreditCardPayment {
    +String token
    +authorize(amount) PaymentResult
  }

  class OrderStatus {
    <<Enumeration>>
    CREATED
    PAID
    CANCELLED
  }

  Customer "1" --> "0..*" Order : places
  Order "1" *-- "1..*" OrderItem : contains
  Order --> PaymentMethod : uses
  PaymentMethod <|.. CreditCardPayment
  Order --> OrderStatus

PlantUML 代码和图

@startuml
left to right direction

class Customer {
  +id: String
  +email: String
  +placeOrder()
}

class Order {
  +id: String
  +status: OrderStatus
  +total: Money
  +addItem(productId, quantity)
  +checkout(): PaymentResult
}

class OrderItem {
  +productId: String
  +quantity: int
  +price: Money
  +subtotal(): Money
}

interface PaymentMethod {
  +authorize(amount): PaymentResult
}

class CreditCardPayment {
  +token: String
  +authorize(amount): PaymentResult
}

enum OrderStatus {
  CREATED
  PAID
  CANCELLED
}

Customer "1" --> "0..*" Order : places
Order "1" *-- "1..*" OrderItem : contains
Order --> PaymentMethod : uses
PaymentMethod <|.. CreditCardPayment
Order --> OrderStatus
@enduml

对这种中小型领域模型,Mermaid 已经可以把结构讲清楚。它不是只能画“几个方框加几条线”;类成员、接口标记、枚举标记、组合关系和基数都能表达。

为什么正式 UML 类图更适合 PlantUML?

PlantUML 官方类图语法直接提供 classinterfaceenumabstract classannotationentityrecorddataclassprotocol 等声明元素。Mermaid 可用 <<Interface>><<Enumeration>> 表示性质,但 PlantUML 的元素类型在源码和图上都更显式。

Mermaid 代码和图

classDiagram
  class Repository {
    <<Interface>>
    +findById(id) Entity
    +save(entity)
  }

  class SqlRepository {
    +findById(id) Entity
    +save(entity)
  }

  class BaseEntity {
    <<Abstract>>
    +String id
    +createdAt Date
  }

  BaseEntity <|-- User
  Repository <|.. SqlRepository

PlantUML 代码和图

@startuml
interface Repository {
  +findById(id): Entity
  +save(entity)
}

class SqlRepository {
  +findById(id): Entity
  +save(entity)
}

abstract class BaseEntity {
  +id: String
  +createdAt: Date
}

class User

BaseEntity <|-- User
Repository <|.. SqlRepository
@enduml

Mermaid 的 annotation 很适合文档说明;PlantUML 的声明元素更适合正式建模,因为读者能从语法和图形上同时看出元素类型。

大型类图如何维护多个视图?

同一领域模型在产品说明中可能只展示公开方法,在设计评审中却要显示字段、抽象类、包结构和内部依赖。PlantUML 的 hide/show/remove/restore 与按标签操作可裁剪成员或类,让同一源模型服务多个读者;这是长期维护层面的直接语法优势。

PlantUML 代码和图

@startuml
skinparam classAttributeIconSize 0
hide empty members

package "order.domain" {
  abstract class AggregateRoot {
    +id: String
    #raise(event)
  }

  class Order {
    -items: List<OrderItem>
    +checkout()
    +cancel()
  }

  class OrderItem {
    -productId: String
    -quantity: int
  }
}

package "payment.domain" {
  interface PaymentGateway {
    +authorize(orderId, amount): PaymentResult
  }

  class StripeGateway {
    +authorize(orderId, amount): PaymentResult
  }
}

AggregateRoot <|-- Order
Order *-- OrderItem
Order ..> PaymentGateway
PaymentGateway <|.. StripeGateway

note right of Order
  Public methods are kept visible
  for the architecture review.
end note
@enduml

Mermaid 近似表达

classDiagram
  namespace order.domain {
    class AggregateRoot {
      <<Abstract>>
      +String id
      #raise(event)
    }

    class Order {
      -List~OrderItem~ items
      +checkout()
      +cancel()
    }

    class OrderItem {
      -String productId
      -int quantity
    }
  }

  namespace payment.domain {
    class PaymentGateway {
      <<Interface>>
      +authorize(orderId, amount) PaymentResult
    }

    class StripeGateway {
      +authorize(orderId, amount) PaymentResult
    }
  }

  AggregateRoot <|-- Order
  Order *-- OrderItem
  Order ..> PaymentGateway
  PaymentGateway <|.. StripeGateway

  note for Order "Public methods are kept visible\nfor the architecture review."

这个场景为什么偏向 PlantUML?

Mermaid 可以近似表达这张图,但能力边界不同:

样式治理与架构分层怎么做?

官网 Mermaid 11.15.0 起支持显示标签和嵌套 namespace,不能再把 namespace 写成 PlantUML 独占能力。跨多张图的规范则可用 PlantUML 的 skinparam、stereotype 样式和包样式集中治理;类图与系统边界的配合请参见软件架构图对比

关联类的专用语法

关联类把一条关系本身当成需要属性或行为的建模元素。PlantUML 官方类图文档提供相应写法;截至核验日,Mermaid 官方类图页未列出对应专用语法。是否能用普通类近似,不应被误写为已有专用 UML 表达。

Mermaid 代码和图

classDiagram
  class DiagramProject {
    +String id
    +String title
    +DiagramType type
    +save()
  }

  class Renderer {
    <<Interface>>
    +render(source) SvgResult
  }

  class MermaidRenderer {
    +render(source) SvgResult
  }

  class PlantUmlRenderer {
    +render(source) SvgResult
  }

  DiagramProject --> Renderer : uses
  Renderer <|.. MermaidRenderer
  Renderer <|.. PlantUmlRenderer

  note for Renderer "A renderer converts diagram source into SVG."

这类图仍能清楚解释一个模块。是否切换到 PlantUML,取决于是否需要正式声明、关联类、裁剪视图和统一样式,而不是图中是否出现继承线。

类图选择结论

选 Mermaid 写类图,如果这张图的重点是:

  • 展示一个中小型领域模型。
  • 说明几个类之间的继承、实现、组合和依赖关系。
  • 读者需要快速看懂结构,而不是审查完整 UML 语义。
  • 图的规模可控,不需要频繁生成多个裁剪视图。

选 PlantUML 写类图,如果这张图的重点是:

  • 表达更正式的 UML 类图语义。
  • 需要直接声明 interfaceenumabstract classrecorddataclass 等元素。
  • 需要 package、namespace、多种包样式或大型模型分组。
  • 需要隐藏属性、隐藏方法、移除元素、展示不同评审视图。
  • 需要关联类、字段/方法注释、链接注释或更复杂的说明结构。
  • 需要稳定的样式规范,例如统一字体、颜色、stereotype 和输出风格。

类图选型有哪些常见问题?

Mermaid 类图支持继承、组合和聚合吗?

支持。Mermaid 官方类图支持继承、组合、聚合、关联、依赖、实现、实线链接和虚线链接等常见关系,也支持关系两端的基数标注。不要因为图里有继承或组合,就直接判断 Mermaid 不够用。

Mermaid 类图支持接口和枚举吗?

支持表达,但方式更偏 annotation。你可以使用 <<Interface>><<Enumeration>> 这类标记说明类的性质。PlantUML 则可以直接使用 interfaceenum 等声明元素,语义更显式。

Mermaid 的嵌套 namespace 仍然不能用吗?

不能这样判断。Mermaid 官网自 11.15.0 起已文档化嵌套 namespace;本项目锁定 11.6.0,因此不能把该新语法直接用于当前版本。PlantUML 的优势应放在关联类、声明元素、裁剪命令、细粒度注释和样式治理。

只看图形能力,Mermaid 和 PlantUML 类图怎么选?

如果图的重点是“让读者快速理解结构”,Mermaid 通常就够了。如果图的重点是“准确表达 UML 语义并维护多个复杂视图”,PlantUML 更合适。

最终结论:

只比较类图表达和长期维护能力,PlantUML 更强,应作为正式 UML 类图的默认选择。 Mermaid 仍是常见对象模型的合格表达方式;当设计需要长期归档和多视图维护时,PlantUML 的语法优势更直接。