UML Diagram (ตอนที่ 1)

บทนำ: ทำไมต้อง UML?

เมื่อเขียนโปรแกรมใหญ่ขึ้น การสื่อสารระหว่างทีมกลายเป็นปัญหา:

  • วิศวกร A เข้าใจระบบไม่เหมือนวิศวกร B
  • เอกสารเป็นตัวหนังสือยาวเหยียด อ่านไม่รู้เรื่อง
  • โค้ดมีหลายพันบรรทัด มองไม่เห็นภาพรวม

UML (Unified Modeling Language) คือ ภาษากลาง ที่ใช้ วาดภาพระบบซอฟต์แวร์ ให้ทุกคนเห็นภาพเดียวกัน

ประโยชน์:

  • 📊 มองเห็นภาพรวม – เข้าใจโครงสร้างระบบได้ทันที
  • 💬 สื่อสารง่าย – ทีมเข้าใจตรงกัน
  • 📝 เป็นเอกสาร – blueprint ก่อนเขียนโค้ด
  • 🔍 วิเคราะห์ปัญหา – เห็นจุดอ่อนของระบบ

UML Diagrams: ภาพรวม 14 ประเภท

UML มี 14 ประเภท แบ่งเป็น 2 กลุ่มใหญ่:

1. Structure Diagrams (โครงสร้าง) – 7 ประเภท

แสดงโครงสร้างคงที่ของระบบ

Diagramความหมายใช้เมื่อ
Class Diagramโครงสร้าง classes และความสัมพันธ์ออกแบบ OOP
Object Diagraminstances ของ objects ในเวลาหนึ่งแสดงตัวอย่างข้อมูล
Component Diagramโครงสร้างของ componentsแบ่งระบบใหญ่
Deployment Diagramการติดตั้งบน hardwareวาง architecture
Package Diagramการจัดกลุ่ม classesจัดระเบียบโปรเจค
Composite Structureโครงสร้างภายใน classออกแบบซับซ้อน
Profile Diagramขยาย UMLปรับแต่ง UML

2. Behavior Diagrams (พฤติกรรม) – 7 ประเภท

แสดงการทำงานและการเปลี่ยนแปลงของระบบ

Diagramความหมายใช้เมื่อ
Use Case Diagramฟังก์ชันของระบบกำหนด requirements
Activity Diagramขั้นตอนการทำงาน (flowchart)วาดกระบวนการ
State Machine Diagramสถานะของ objectlifecycle ของ object
Sequence Diagramลำดับการส่งข้อความinteraction ตามเวลา
Communication Diagramการสื่อสารระหว่าง objectsinteraction แบบเน้น structure
Timing Diagramเวลาในการทำงานreal-time systems
Interaction Overviewภาพรวม interactionsรวม sequence diagrams

Class Diagram: Diagram สำคัญที่สุด

Class Diagram คือ ไดอะแกรมที่สำคัญที่สุด ใน UML สำหรับ OOP

แสดง:

  • Classes ที่มีในระบบ
  • Attributes และ Methods ของแต่ละ class
  • ความสัมพันธ์ระหว่าง classes

โครงสร้าง Class Diagram

Class Box: กล่องแสดง Class

text┌──────────────────────┐
│   ClassName          │  ← ชื่อ class
├──────────────────────┤
│   - attribute1: type │  ← attributes
│   - attribute2: type │
├──────────────────────┤
│   + method1(): type  │  ← methods
│   + method2(): type  │
└──────────────────────┘

แบ่งเป็น 3 ส่วน:

  1. ส่วนบน – ชื่อ class
  2. ส่วนกลาง – attributes (fields)
  3. ส่วนล่าง – methods (operations)

Access Modifiers: สัญลักษณ์การเข้าถึง

สัญลักษณ์ความหมายJava
+publicpublic
-privateprivate
#protectedprotected
~package/defaultไม่ระบุ

ตัวอย่าง: Class Diagram แรก

Code:

javapublic class Student {
    private String studentID;
    private String name;
    private double gpa;
    
    public Student(String studentID, String name, double gpa) {
        this.studentID = studentID;
        this.name = name;
        this.gpa = gpa;
    }
    
    public void study() {
        gpa += 0.1;
    }
    
    public double getGPA() {
        return gpa;
    }
    
    public void displayInfo() {
        System.out.println("ID: " + studentID);
    }
}

Class Diagram:

text┌─────────────────────────┐
│       Student           │
├─────────────────────────┤
│ - studentID: String     │
│ - name: String          │
│ - gpa: double           │
├─────────────────────────┤
│ + Student(id, name, gpa)│
│ + study(): void         │
│ + getGPA(): double      │
│ + displayInfo(): void   │
└─────────────────────────┘

ตัวอย่าง: Static Members

Code:

javapublic class BankAccount {
    private static String bankName = "Bangkok Bank";
    private static int totalAccounts = 0;
    
    private String accountNumber;
    private double balance;
    
    public BankAccount(String accountNumber, double balance) {
        this.accountNumber = accountNumber;
        this.balance = balance;
        BankAccount.totalAccounts++;
    }
    
    public void deposit(double amount) {
        balance += amount;
    }
    
    public static int getTotalAccounts() {
        return totalAccounts;
    }
}

Class Diagram:

text┌────────────────────────────────┐
│       BankAccount              │
├────────────────────────────────┤
│ - bankName: String {static}    │  ← static = underline
│ - totalAccounts: int {static}  │
│ - accountNumber: String        │
│ - balance: double              │
├────────────────────────────────┤
│ + BankAccount(num, bal)        │
│ + deposit(amount): void        │
│ + getTotalAccounts(): int {static} │
└────────────────────────────────┘

หมายเหตุ: Static members ใช้ underline (ขีดเส้นใต้)


Relationships: ความสัมพันธ์ระหว่าง Classes

Class Diagram ไม่ได้มีแค่ classes เดี่ยวๆ แต่แสดงความสัมพันธ์ด้วย

มี 6 ประเภทหลัก:

1. Association (เชื่อมโยง)

ความหมาย: Class A รู้จัก Class B (มีการใช้งานกัน)

สัญลักษณ์: เส้นตรง ────

ตัวอย่าง: Teacher สอน Student

text┌──────────┐            ┌──────────┐
│ Teacher  │────────────│ Student  │
└──────────┘   teaches  └──────────┘

Code:

javapublic class Teacher {
    private String name;
    
    public void teach(Student student) {
        // Teacher ใช้งาน Student
        System.out.println("Teaching " + student.getName());
    }
}

public class Student {
    private String name;
    
    public String getName() {
        return name;
    }
}

2. Aggregation (รวมกัน – แบบหลวม)

ความหมาย: Class A มี Class B แต่ B สามารถอยู่ได้โดยไม่มี A

สัญลักษณ์: เส้น + ข้าวหลามตัดขาว ◇────

ตัวอย่าง: Department มี Teacher

text┌────────────┐         ┌──────────┐
│ Department │◇────────│ Teacher  │
└────────────┘         └──────────┘
   contains

Code:

javapublic class Department {
    private String deptName;
    private ArrayList<Teacher> teachers;  // มี teachers
    
    public void addTeacher(Teacher teacher) {
        teachers.add(teacher);
    }
}

public class Teacher {
    private String name;
    // Teacher สามารถอยู่ได้โดยไม่มี Department
}

หมายเหตุ: ถ้าลบ Department, Teacher ยังอยู่ได้


3. Composition (ประกอบด้วย – แบบแน่น)

ความหมาย: Class A มี Class B และ B ไม่สามารถอยู่ได้โดยไม่มี A

สัญลักษณ์: เส้น + ข้าวหลามตัดดำ ◆────

ตัวอย่าง: House มี Room

text┌────────┐          ┌────────┐
│ House  │◆─────────│ Room   │
└────────┘          └────────┘
  contains

Code:

javapublic class House {
    private String address;
    private Room[] rooms;  // มี rooms
    
    public House(String address) {
        this.address = address;
        // สร้าง rooms พร้อม house
        this.rooms = new Room[5];
        for (int i = 0; i < 5; i++) {
            rooms[i] = new Room(i + 1);
        }
    }
}

public class Room {
    private int roomNumber;
    
    public Room(int roomNumber) {
        this.roomNumber = roomNumber;
    }
    // Room ไม่สามารถอยู่ได้โดยไม่มี House
}

หมายเหตุ: ถ้าลบ House, Room จะถูกลบด้วย


4. Inheritance (สืบทอด)

ความหมาย: Class B สืบทอดจาก Class A (IS-A relationship)

สัญลักษณ์: เส้น + ลูกศรสามเหลี่ยมขาว ◁────

ตัวอย่าง: Dog สืบทอด Animal

text     ┌────────┐
     │ Animal │
     └────────┘
         △
         │
         │
     ┌────────┐
     │  Dog   │
     └────────┘

Code:

javapublic class Animal {
    protected String name;
    
    public void eat() {
        System.out.println("Eating...");
    }
}

public class Dog extends Animal {
    public void bark() {
        System.out.println("Woof!");
    }
}

5. Realization/Implementation (ทำตาม Interface)

ความหมาย: Class B ทำตาม Interface A

สัญลักษณ์: เส้นประ + ลูกศรสามเหลี่ยมขาว ◁┄┄┄

ตัวอย่าง: Dog ทำตาม Runnable

text    ┌──────────────┐
    │ <<interface>>│
    │  Runnable    │
    └──────────────┘
         △
        ┆┆┆
         │
     ┌────────┐
     │  Dog   │
     └────────┘

Code:

javapublic interface Runnable {
    void run();
}

public class Dog implements Runnable {
    @Override
    public void run() {
        System.out.println("Dog is running");
    }
}

6. Dependency (พึ่งพา)

ความหมาย: Class A ใช้ Class B แต่ไม่ได้เก็บเป็น attribute

สัญลักษณ์: เส้นประ + ลูกศร ←┄┄┄

ตัวอย่าง: Calculator ใช้ Math

text┌────────────┐       ┌──────┐
│ Calculator │┄┄┄┄┄┄>│ Math │
└────────────┘ uses  └──────┘

Code:

javapublic class Calculator {
    public double calculateArea(double radius) {
        // ใช้ Math แต่ไม่ได้เก็บเป็น attribute
        return Math.PI * radius * radius;
    }
}

ตัวอย่างที่ 1: ระบบจัดการนักศึกษา

Code

java// Class 1: Person (Base class)
public class Person {
    protected String id;
    protected String name;
    protected int age;
    
    public Person(String id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }
    
    public void displayInfo() {
        System.out.println("ID: " + id + ", Name: " + name);
    }
}

// Class 2: Student (Inherits Person)
public class Student extends Person {
    private double gpa;
    private Course[] enrolledCourses;
    
    public Student(String id, String name, int age, double gpa) {
        super(id, name, age);
        this.gpa = gpa;
        this.enrolledCourses = new Course[10];
    }
    
    public void enrollCourse(Course course) {
        // เพิ่ม course
    }
}

// Class 3: Course
public class Course {
    private String courseCode;
    private String courseName;
    private Teacher teacher;  // Aggregation
    
    public Course(String code, String name) {
        this.courseCode = code;
        this.courseName = name;
    }
    
    public void assignTeacher(Teacher teacher) {
        this.teacher = teacher;
    }
}

// Class 4: Teacher (Inherits Person)
public class Teacher extends Person {
    private String department;
    
    public Teacher(String id, String name, int age, String dept) {
        super(id, name, age);
        this.department = dept;
    }
}

Class Diagram

text                ┌─────────────────┐
                │     Person      │
                ├─────────────────┤
                │ # id: String    │
                │ # name: String  │
                │ # age: int      │
                ├─────────────────┤
                │ + Person(...)   │
                │ + displayInfo() │
                └─────────────────┘
                        △
                        │
            ┌───────────┴───────────┐
            │                       │
    ┌───────────────┐       ┌──────────────┐
    │   Student     │       │   Teacher    │
    ├───────────────┤       ├──────────────┤
    │ - gpa: double │       │ - department │
    ├───────────────┤       ├──────────────┤
    │ + Student(...)│       │ + Teacher(...)│
    │ + enrollCourse│       └──────────────┘
    └───────────────┘               │
            │                       │
            │ enrolls              teaches
            │                       │
            ↓                       ↓
    ┌────────────────────────────────────┐
    │          Course                    │
    ├────────────────────────────────────┤
    │ - courseCode: String               │
    │ - courseName: String               │
    ├────────────────────────────────────┤
    │ + Course(code, name)               │
    │ + assignTeacher(teacher): void     │
    └────────────────────────────────────┘

ความสัมพันธ์:

  • Person ← Student (Inheritance)
  • Person ← Teacher (Inheritance)
  • Student → Course (Association)
  • Course ◇→ Teacher (Aggregation)

Multiplicity: จำนวนความสัมพันธ์

Multiplicity บอกจำนวนของ objects ที่เกี่ยวข้อง

สัญลักษณ์ความหมาย
1หนึ่งเดียว
0..1ศูนย์ หรือ หนึ่ง
* หรือ 0..*ศูนย์ หรือ มากกว่า
1..*หนึ่ง หรือ มากกว่า
nn เท่านั้น
n..mn ถึง m

ตัวอย่าง: Multiplicity

text┌──────────┐  1      *  ┌──────────┐
│ Teacher  │────────────│ Student  │
└──────────┘  teaches   └──────────┘

ความหมาย:

  • 1 Teacher สอนได้หลาย Students (*)
  • หลาย Students (*) เรียนกับ 1 Teacher

text┌──────────┐  1      1..*  ┌──────────┐
│ Company  │───────────────│ Employee │
└──────────┘    employs    └──────────┘

ความหมาย:

  • 1 Company มีอย่างน้อย 1 Employee (1..*)
  • หลาย Employees (1..*) ทำงานกับ 1 Company

text┌──────────┐  *      *  ┌──────────┐
│ Student  │────────────│ Course   │
└──────────┘  enrolls   └──────────┘

ความหมาย:

  • หลาย Students () ลงทะเบียนหลาย Courses ()
  • หลาย Courses () มีหลาย Students ()

ตัวอย่างที่ 2: ระบบห้องสมุด (Library System)

Requirements

textระบบห้องสมุด:
- มี Books หลายเล่ม
- มี Members หลายคน
- Member ยืม Books ได้
- มีการบันทึก BorrowRecords

Code

java// Class 1: Book
public class Book {
    private String isbn;
    private String title;
    private String author;
    private int quantity;
    private int availableCopies;
    
    public Book(String isbn, String title, String author, int quantity) {
        this.isbn = isbn;
        this.title = title;
        this.author = author;
        this.quantity = quantity;
        this.availableCopies = quantity;
    }
    
    public boolean isAvailable() {
        return availableCopies > 0;
    }
    
    public void borrowBook() {
        if (availableCopies > 0) {
            availableCopies--;
        }
    }
    
    public void returnBook() {
        if (availableCopies < quantity) {
            availableCopies++;
        }
    }
}

// Class 2: Member
public class Member {
    private String memberID;
    private String name;
    private String email;
    private ArrayList<BorrowRecord> borrowHistory;
    
    public Member(String memberID, String name, String email) {
        this.memberID = memberID;
        this.name = name;
        this.email = email;
        this.borrowHistory = new ArrayList<>();
    }
    
    public BorrowRecord borrowBook(Book book) {
        if (book.isAvailable()) {
            book.borrowBook();
            BorrowRecord record = new BorrowRecord(this, book);
            borrowHistory.add(record);
            return record;
        }
        return null;
    }
}

// Class 3: BorrowRecord
public class BorrowRecord {
    private String recordID;
    private Member member;
    private Book book;
    private LocalDate borrowDate;
    private LocalDate returnDate;
    
    public BorrowRecord(Member member, Book book) {
        this.recordID = generateID();
        this.member = member;
        this.book = book;
        this.borrowDate = LocalDate.now();
        this.returnDate = null;
    }
    
    public void returnBook() {
        this.returnDate = LocalDate.now();
        book.returnBook();
    }
    
    private String generateID() {
        return "R" + System.currentTimeMillis();
    }
}

// Class 4: Library (Main system)
public class Library {
    private String libraryName;
    private ArrayList<Book> books;
    private ArrayList<Member> members;
    
    public Library(String name) {
        this.libraryName = name;
        this.books = new ArrayList<>();
        this.members = new ArrayList<>();
    }
    
    public void addBook(Book book) {
        books.add(book);
    }
    
    public void registerMember(Member member) {
        members.add(member);
    }
}

Class Diagram

text┌──────────────────────────────┐
│         Library              │
├──────────────────────────────┤
│ - libraryName: String        │
├──────────────────────────────┤
│ + Library(name)              │
│ + addBook(book): void        │
│ + registerMember(m): void    │
└──────────────────────────────┘
       │                │
       │ 1           1  │
       │                │
       │ *           *  │
       ↓                ↓
┌───────────┐   *   *  ┌────────────────┐
│   Book    │──────────│    Member      │
├───────────┤  borrows ├────────────────┤
│ - isbn    │          │ - memberID     │
│ - title   │          │ - name         │
│ - author  │          │ - email        │
│ - quantity│          ├────────────────┤
├───────────┤          │ + borrowBook() │
│ + borrow()│          └────────────────┘
│ + return()│                   │
└───────────┘                   │ 1
       △                        │
       │                        │ *
       │ 1                      ↓
       │              ┌──────────────────┐
       └──────────────│  BorrowRecord    │
              records ├──────────────────┤
                      │ - recordID       │
                      │ - borrowDate     │
                      │ - returnDate     │
                      ├──────────────────┤
                      │ + returnBook()   │
                      └──────────────────┘

ความสัมพันธ์:

  • Library ◆→ Book (Composition – 1 to *)
  • Library ◆→ Member (Composition – 1 to *)
  • Member → Book (Association – * to *)
  • Member ◆→ BorrowRecord (Composition – 1 to *)
  • BorrowRecord → Book (Association – * to 1)

Abstract Class และ Interface ใน UML

Abstract Class

สัญลักษณ์: ชื่อเป็น italic หรือ {abstract}

text┌──────────────────┐
│  <<abstract>>    │
│    Animal        │
├──────────────────┤
│ # name: String   │
├──────────────────┤
│ + eat(): void    │
│ + sleep(): void  │
│ + move(): void {abstract} │
└──────────────────┘
        △
        │
    ┌───┴───┐
    │       │
┌───────┐ ┌───────┐
│  Dog  │ │  Cat  │
└───────┘ └───────┘

Code:

javapublic abstract class Animal {
    protected String name;
    
    public void eat() {
        System.out.println("Eating...");
    }
    
    public void sleep() {
        System.out.println("Sleeping...");
    }
    
    public abstract void move();  // Abstract method
}

public class Dog extends Animal {
    @Override
    public void move() {
        System.out.println("Running");
    }
}

public class Cat extends Animal {
    @Override
    public void move() {
        System.out.println("Walking");
    }
}

Interface

สัญลักษณ์: <<interface>> หรือ <<I>>

text┌──────────────────┐
│  <<interface>>   │
│    Drawable      │
├──────────────────┤
│ + draw(): void   │
└──────────────────┘
        △
       ┆┆┆
        │
    ┌───┴───┐
    │       │
┌────────┐ ┌────────┐
│ Circle │ │ Square │
└────────┘ └────────┘

Code:

javapublic interface Drawable {
    void draw();
}

public class Circle implements Drawable {
    @Override
    public void draw() {
        System.out.println("Drawing circle");
    }
}

public class Square implements Drawable {
    @Override
    public void draw() {
        System.out.println("Drawing square");
    }
}

สรุปตอนที่ 1

เราได้เรียนรู้:

✅ UML คืออะไร – ภาษากลางสำหรับวาดภาพซอฟต์แวร์
✅ 14 Diagrams – แบ่งเป็น Structure และ Behavior
✅ Class Diagram พื้นฐาน – Class box 3 ส่วน
✅ Access Modifiers – +, -, #, ~
✅ 6 Relationships – Association, Aggregation, Composition, Inheritance, Realization, Dependency
✅ Multiplicity – 1, 0..1, , 1.. เป็นต้น
✅ Abstract และ Interface – ใน UML


ตัวอย่างท้ายตอน: E-Commerce System (Partial)

text┌──────────────┐  1     *  ┌──────────────┐
│   Customer   │───────────│    Order     │
├──────────────┤  places   ├──────────────┤
│ - customerID │           │ - orderID    │
│ - name       │           │ - orderDate  │
│ - email      │           │ - status     │
├──────────────┤           ├──────────────┤
│ + register() │           │ + addItem()  │
│ + login()    │           │ + checkout() │
└──────────────┘           └──────────────┘
                                  │
                                  │ 1
                                  │
                                  │ *
                                  ↓
                          ┌──────────────┐
                          │  OrderItem   │
                          ├──────────────┤
                          │ - quantity   │
                          │ - price      │
                          ├──────────────┤
                          │ + getTotal() │
                          └──────────────┘
                                  │
                                  │ *
                                  │
                                  │ 1
                                  ↓
                          ┌──────────────┐
                          │   Product    │
                          ├──────────────┤
                          │ - productID  │
                          │ - name       │
                          │ - price      │
                          ├──────────────┤
                          │ + getInfo()  │
                          └──────────────┘

🎯 ในตอนต่อไป เราจะเรียนรู้:

  • Behavior Diagrams แบบละเอียด
  • Use Case Diagram
  • Sequence Diagram
  • Activity Diagram
  • ตัวอย่างระบบใหญ่ที่สมบูรณ์