μƒˆμ†Œμ‹

Java

[JAVA] μŠ€ν”„λ§κ³Ό 객체지ν–₯

  • -
728x90

객체 지ν–₯ ν”„λ‘œκ·Έλž˜λ°μ€ 컴퓨터 ν”„λ‘œκ·Έλž¨μ„ λͺ…λ Ήμ–΄μ˜ λͺ©λ‘μœΌλ‘œ λ³΄λŠ” μ‹œκ°μ—μ„œ λ²—μ–΄λ‚˜ μ—¬λŸ¬ 개의 λ…λ¦½λœ λ‹¨μœ„, 즉 "객체" λ“€μ˜ λͺ¨μž„μœΌλ‘œ νŒŒμ•…ν•˜κ³ μž ν•˜λŠ” 것이닀. 각각의 κ°μ²΄λŠ” 메세지λ₯Ό μ£Όκ³ λ°›κ³ , 데이터λ₯Ό μ²˜λ¦¬ν•  수 μžˆλ‹€. (ν˜‘λ ₯)

객체지ν–₯ ν”„λ‘œκ·Έλž˜λ°μ€ ν”„λ‘œκ·Έλž¨μ„ μœ μ—°ν•˜κ³  변경이 μš©μ΄ν•˜κ²Œ λ§Œλ“€κΈ° λ•Œλ¬Έμ— λŒ€κ·œλͺ¨ μ†Œν”„νŠΈμ›¨μ–΄μ˜ κ°œλ°œμ— 많이 μ‚¬μš©λœλ‹€.

ν”„λ‘œκ·Έλž¨μ„ 섀계할 λ•Œ, μžλ°” μ–Έμ–΄μ˜ λ‹€ν˜•μ„±μ„ ν™œμš©ν•˜μ—¬ μ—­ν• κ³Ό κ΅¬ν˜„μ„ λͺ…ν™•νžˆ 뢄리해야 ν•œλ‹€.

 

μ—­ν•  = μΈν„°νŽ˜μ΄μŠ€
κ΅¬ν˜„ = μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•œ 클래슀, κ΅¬ν˜„ 객체

 

객체 μ„€κ³„μ‹œ μ—­ν• (μΈν„°νŽ˜μ΄μŠ€)λ₯Ό λ¨Όμ € λΆ€μ—¬ν•˜κ³ , κ·Έ 역할을 μˆ˜ν–‰ν•˜λŠ” κ΅¬ν˜„ 객체λ₯Ό λ§Œλ“ λ‹€.

 

λ‹€ν˜•μ„±μ˜ λ³Έμ§ˆμ΄λž€

μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•œ 객체 μΈμŠ€ν„΄μŠ€λ₯Ό μ‹€ν–‰ μ‹œμ μ— μœ μ—°ν•˜κ²Œ λ³€κ²½ν•  수 μžˆλ‹€. λ‹€ν˜•μ„±μ˜ λ³Έμ§ˆμ„ μ΄ν•΄ν•˜λ €λ©΄ ν˜‘λ ₯μ΄λΌλŠ” κ°μ²΄μ‚¬μ΄μ˜ κ΄€κ³„μ—μ„œ μ‹œμž‘ν•΄μ•Ό ν•œλ‹€. ν΄λΌμ΄μ–ΈνŠΈλ₯Ό λ³€κ²½ν•˜μ§€ μ•Šκ³ , μ„œλ²„μ˜ κ΅¬ν˜„ κΈ°λŠ₯을 μœ μ—°ν•˜κ²Œ λ³€κ²½ν•  수 μžˆλ‹€.

즉, μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ•ˆμ •μ μœΌλ‘œ 잘 μ„€κ³„ν•˜λŠ” 것이 μ€‘μš”ν•˜λ‹€.

 

μŠ€ν”„λ§κ³Ό 객체지ν–₯

λ‹€ν˜•μ„±μ΄ 제일 μ€‘μš”ν•˜κ³ , μŠ€ν”„λ§μ€ 이 λ‹€ν˜•μ„±μ„ κ·ΉλŒ€ν™”ν•΄μ„œ μ΄μš©ν•  수 있게 도와쀀닀. μŠ€ν”„λ§μ—μ„œ μ΄μ•ΌκΈ°ν•˜λŠ” μ œμ–΄μ˜ μ—­μ „ (IoC), μ˜μ‘΄κ΄€κ³„ μ£Όμž…(DI)은 λ‹€ν˜•μ„±μ„ ν™œμš©ν•΄μ„œ μ—­ν• κ³Ό κ΅¬ν˜„μ„ νŽΈλ¦¬ν•˜κ²Œ λ‹€λ£° 수 μžˆλ„λ‘ μ§€μ›ν•œλ‹€.

 

  1. 단일 μ±…μž„ 원칙 (Single Responsibility principle)
  2. 개방 폐쇄 원칙 (Open Closed Principle)
  3. λ¦¬μŠ€μ½”ν”„ μΉ˜ν™˜ 원칙 (Liscov Substitution Principle)
  4. μΈν„°νŽ˜μ΄μŠ€ 뢄리 원칙 (Interface Sergregation Principle)
  5. μ˜μ‘΄μ„± μ—­μ „ 원칙 (Dependency Inversion Principle)

1. SRP, 단일 μ±…μž„ 원칙

ν•œ ν΄λž˜μŠ€λŠ” ν•˜λ‚˜μ˜ μ±…μž„λ§Œ κ°€μ Έμ•Ό ν•œλ‹€. ν•˜λ‚˜μ˜ μ±…μž„μ΄λΌλŠ” 것은 클 μˆ˜λ„ μž‘μ„ μˆ˜λ„ 있고, λ¬Έλ§₯κ³Ό 상황에 따라 λ‹€λ₯΄κΈ° λ•Œλ¬Έμ— λͺ¨ν˜Έν•˜λ‹€.

μ€‘μš”ν•œ 기쀀은 변경이닀. 변경이 μžˆμ„ λ•Œ νŒŒκΈ‰ νš¨κ³Όκ°€ 적으면 단일 μ±…μž„ 원칙을 잘 λ”°λ₯Έ κ²ƒμ΄λΌλŠ” 말이닀. (UI λ³€κ²½, 객체의 생성과 μ‚¬μš©μ„ 뢄리)

 

// μ‚¬μš©μžμ˜ 정보λ₯Ό μ·¨κΈ‰ν•˜λŠ” 클래슀
class User {
    private String name;
    private String email;

    public User(String name, String email) {
        this.name = name;
        this.email = email;
    }

    // Getters and Setters
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
}

// λ°μ΄ν„°λ² μ΄μŠ€ κ΄€λ ¨ λ‘œμ§μ„ μ²˜λ¦¬ν•˜λŠ” 클래슀
class UserRepository {
    public void saveUser(User user) {
        // 여기에 λ°μ΄ν„°λ² μ΄μŠ€ μ €μž₯ 둜직 κ΅¬ν˜„
    }
}

 

μœ„μ˜ μ½”λ“œλ₯Ό μ˜ˆμ‹œλ‘œ, μ‚¬μš©μž 정보λ₯Ό κ΄€λ¦¬ν•˜λŠ” ν΄λž˜μŠ€μ™€ μ‚¬μš©μžμ˜ 데이터λ₯Ό λ°μ΄ν„°λ² μ΄μŠ€μ— μ €μž₯ν•˜λŠ” λ‘œμ§μ„ 뢄리할 수 μžˆλ‹€.

 

2. OCP, 개방 폐쇄 원칙

μ†Œν”„νŠΈμ›¨μ–΄ μš”μ†ŒλŠ” ν™•μž₯μ—λŠ” μ—΄λ € μžˆμœΌλ‚˜ λ³€κ²½μ—λŠ” λ‹«ν˜€ μžˆμ–΄μ•Ό ν•œλ‹€. μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•œ μƒˆλ‘œμš΄ 클래슀λ₯Ό ν•˜λ‚˜ λ§Œλ“€μ–΄μ„œ μƒˆλ‘œμš΄ κΈ°λŠ₯을 κ΅¬ν˜„, λ‹€ν˜•μ„±μ˜ ν™œμš©μ΄ κ°€λŠ₯ν•˜λ‹€. 기쑴의 μ½”λ“œλ₯Ό λ³€κ²½ν•˜μ§€ μ•Šκ³ λ„, 클래슀의 κΈ°λŠ₯을 ν™•μž₯ν•  수 μžˆμ–΄μ•Ό ν•œλ‹€.

 

abstract class Shape {
    abstract double calculateArea();
}

class Rectangle extends Shape {
    private double width;
    private double height;

    public Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }

    @Override
    public double calculateArea() {
        return width * height;
    }
}

class Circle extends Shape {
    private double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    @Override
    public double calculateArea() {
        return Math.PI * radius * radius;
    }
}

 

μ—¬κΈ°μ„œ 'Discount' ν΄λž˜μŠ€λŠ” 좔상 클래슀둜, λ‹€μ–‘ν•œ ν• μΈμœ¨μ„ μ μš©ν•  수 μžˆλ„λ‘ ν™•μž₯이 κ°€λŠ₯ν•˜λ‚˜ κΈ°μ‘΄ 할인 계산 λ‘œμ§μ„ λ³€κ²½ν•  ν•„μš”κ°€ μ—†λ‹€. μƒˆλ‘œμš΄ ν• μΈμœ¨μ„ μΆ”κ°€ν•˜κ³  싢을 λ•ŒλŠ” 'Discount' λ₯Ό μƒμ†λ°›λŠ” μƒˆλ‘œμš΄ 클래슀λ₯Ό λ§Œλ“€κΈ°λ§Œ ν•˜λ©΄ λœλ‹€.

 

3. LSP, λ¦¬μŠ€μ½”ν”„ μΉ˜ν™˜ 원칙

ν”„λ‘œκ·Έλž¨ κ°μ²΄λŠ” ν”„λ‘œκ·Έλž¨μ˜ 정확성을 κΉ¨λœ¨λ¦¬μ§€ μ•ŠμœΌλ©΄μ„œ ν•˜μœ„ νƒ€μž…μ˜ μΈμŠ€ν„΄μŠ€λ‘œ λ°”κΏ€ 수 μžˆμ–΄μ•Ό ν•œλ‹€. 즉, λΆ€λͺ¨ 클래슀의 μΈμŠ€ν„΄μŠ€ λŒ€μ‹  μžμ‹ 클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό μ‚¬μš©ν•  수 μžˆμ–΄μ•Ό ν•œλ‹€λŠ” μ˜λ―Έμ΄λ‹€. λ‹€ν˜•μ„±μ—μ„œ ν•˜μœ„ ν΄λž˜μŠ€λŠ” μΈν„°νŽ˜μ΄μŠ€ κ·œμ•½μ„ λ‹€ μ§€μΌœμ•Ό ν•œλ‹€λŠ” 것, λ‹€ν˜•μ„±μ„ μ§€μ›ν•˜κΈ° μœ„ν•œ 원칙, μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•œ κ΅¬ν˜„μ²΄λŠ” λ―Ώκ³  μ‚¬μš©ν•˜λ €λ©΄, 이 원칙이 ν•„μš”ν•˜λ‹€.

ex) μžλ™μ°¨ μΈν„°νŽ˜μ΄μŠ€μ˜ 엑셀은 μ•žμœΌλ‘œ κ°€λΌλŠ” κΈ°λŠ₯, λ’€λ‘œ κ°€κ²Œ κ΅¬ν˜„ν•˜λ©΄ LSP μœ„λ°˜, λŠλ¦¬λ”λΌλ„ μ•žμœΌλ‘œ κ°€μ•Ό ν•œλ‹€.

class Bird {
    public void fly() {
        System.out.println("This bird can fly.");
    }
}

class Duck extends Bird {
    @Override
    public void fly() {
        System.out.println("Duck flies lower.");
    }
}

class Ostrich extends Bird {
    @Override
    public void fly() {
        throw new UnsupportedOperationException("Ostrich cannot fly.");
    }
}

 

μœ„μ˜ μ˜ˆμ‹œμ—μ„œ Bird ν΄λž˜μŠ€λŠ” fly() λ©”μ„œλ“œλ₯Ό 가지고 있고, Duck은 이 λ©”μ„œλ“œλ₯Ό μ˜€λ²„λΌμ΄λ“œν•˜μ—¬ λ‹€λ₯΄κ²Œ κ΅¬ν˜„ν•œλ‹€. ν•˜μ§€λ§Œ, Ostrich ν΄λž˜μŠ€λŠ” fly() λ©”μ„œλ“œλ₯Ό μ§€μ›ν•˜μ§€ μ•ŠλŠ”λ‹€. 이 경우 λ¦¬μŠ€μ½”ν”„ μΉ˜ν™˜ 원칙에 μœ„λ°°λœλ‹€. μ™œλƒν•˜λ©΄ Bird νƒ€μž…μ˜ 객체λ₯Ό Ostrich 객체둜 λŒ€μ²΄ν–ˆμ„ λ•Œ, ν”„λ‘œκ·Έλž¨μ΄ μ‹€νŒ¨ν•˜κ²Œ 되기 λ•Œλ¬Έμ΄λ‹€.

 

원칙에 맞게 μˆ˜μ •λœ μ½”λ“œ

class Bird {
}

class FlyingBird extends Bird {
    public void fly() {
        System.out.println("This bird can fly.");
    }
}

class Duck extends FlyingBird {
    @Override
    public void fly() {
        System.out.println("Duck flies lower.");
    }
}

class Ostrich extends Bird {
    // Ostrich ν΄λž˜μŠ€λŠ” FlyingBirdλ₯Ό 상속받지 μ•ŠμŒ
}

 

 

μœ„ μˆ˜μ •λœ μ˜ˆμ‹œμ—μ„œ, λΉ„ν–‰ κ°€λŠ₯ν•œ μƒˆλ“€μ„ μœ„ν•œ λ³„λ„μ˜ 클래슀 FlyingBirdκ°€ λ„μž…λ˜μ—ˆλ‹€. 이둜써, OstrichλŠ” 비행을 κ΅¬ν˜„ν•˜λŠ” 클래슀λ₯Ό 상속받지 μ•ŠμœΌλ―€λ‘œ, Bird νƒ€μž…μ˜ 객체λ₯Ό Ostrich 객체둜 λŒ€μ²΄ν•˜λŠ” μƒν™©μ—μ„œ λΉ„ν–‰ κΈ°λŠ₯을 ν˜ΈμΆœν•  일이 없어지며 λ¦¬μŠ€μ½”ν”„ μΉ˜ν™˜ 원칙을 μ€€μˆ˜ν•˜κ²Œ λœλ‹€.

 

4. ISP, μΈν„°νŽ˜μ΄μŠ€ 뢄리 원칙

νŠΉμ • ν΄λΌμ΄μ–ΈνŠΈλ₯Ό μœ„ν•œ μΈν„°νŽ˜μ΄μŠ€ μ—¬λŸ¬ κ°œκ°€ λ²”μš© μΈν„°νŽ˜μ΄μŠ€ ν•˜λ‚˜λ³΄λ‹€ λ‚«λ‹€. 예λ₯Ό λ“€μ–΄ μžλ™μ°¨ μΈν„°νŽ˜μ΄μŠ€λ₯Ό μš΄μ „ & μ •λΉ„ μΈν„°νŽ˜μ΄μŠ€λ‘œ λΆ„λ¦¬ν•˜κ³  μ‚¬μš©μž ν΄λΌμ΄μ–ΈνŠΈλ₯Ό μš΄μ „μž & 정비사 ν΄λΌμ΄μ–ΈνŠΈλ‘œ λΆ„λ¦¬ν•œλ‹€. λΆ„λ¦¬ν•˜λ©΄ μ •λΉ„ μΈν„°νŽ˜μ΄μŠ€ μžμ²΄κ°€ λ³€κ²½λ˜λ„ μš΄μ „μž ν΄λΌμ΄μ–ΈνŠΈμ— 영ν–₯을 주지 μ•ŠλŠ”λ‹€. μΈν„°νŽ˜μ΄μŠ€κ°€ λͺ…확해지고, λŒ€μ²΄ κ°€λŠ₯성이 높아진닀.

 

interface Printer {
    void printDocument(String document);
}

interface Scanner {
    void scanDocument(String document);
}

class SimplePrinter implements Printer {
    public void printDocument(String document) {
        // Printing logic
    }
}

class MultiFunctionMachine implements Printer, Scanner {
    public void printDocument(String document) {
        // Printing logic
    }

    public void scanDocument(String document) {
        // Scanning logic
    }
}

 

이 μ˜ˆμ‹œμ—μ„œ `SimplePrinter` λŠ” 인쇄 κΈ°λŠ₯만 ν•„μš”λ‘œ ν•˜κ³ ,  `MultiFunctionMachine`은 인쇄와 μŠ€μΊ” κΈ°λŠ₯ λͺ¨λ‘λ₯Ό ν•„μš”λ‘œ ν•œλ‹€. 각각의 ν΄λž˜μŠ€λŠ” μžμ‹ μ΄ ν•„μš”λ‘œ ν•˜λŠ” μΈν„°νŽ˜μ΄μŠ€λ§Œ κ΅¬ν˜„ν•˜λ©΄ λœλ‹€.

 

5. DIP, μ˜μ‘΄κ΄€κ³„ μ—­μ „ 원칙

"좔상화에 μ˜μ‘΄ν•΄μ•Όμ§€, ꡬ체화에 μ˜μ‘΄ν•˜λ©΄ μ•ˆλœλ‹€." μ˜μ‘΄μ„± μ£Όμž…μ€ 이 원칙을 λ”°λ₯΄λŠ” 방법 쀑 ν•˜λ‚˜λ‹€. κ΅¬ν˜„ ν΄λž˜μŠ€μ— μ˜μ‘΄ν•˜μ§€ 말고, μΈν„°νŽ˜μ΄μŠ€μ— μ˜μ‘΄ν•˜λΌλŠ” μ˜λ―Έμ΄λ‹€. 역할에 μ˜μ‘΄ν•˜κ²Œ ν•΄μ•Ό ν•œλ‹€λŠ” 것과 κ°™λ‹€. 객체 세상도 ν΄λΌμ΄μ–ΈνŠΈκ°€ μΈν„°νŽ˜μ΄μŠ€μ— μ˜μ‘΄ν•΄μ•Ό μœ μ—°ν•˜κ²Œ κ΅¬ν˜„μ²΄λ₯Ό λ³€κ²½ν•  수 μžˆλ‹€. κ΅¬ν˜„μ²΄μ— μ˜μ‘΄ν•˜κ²Œ 되면 변경이 μ–΄λ €μ›Œμ§„λ‹€.

 

interface Storage {
    void saveData(String data);
}

class DiskStorage implements Storage {
    public void saveData(String data) {
        // Save data to disk
    }
}

class CloudStorage implements Storage {
    public void saveData(String data) {
        // Save data to cloud
    }
}

class DataManager {
    private Storage storage;

    public DataManager(Storage storage) {
        this.storage = storage;
    }

    public void save(String data) {
        storage.saveData(data);
    }
}

 

`DataManager` ν΄λž˜μŠ€λŠ” ꡬ체적인 `Storage` κ΅¬ν˜„μ²΄μ— μ˜μ‘΄ν•˜μ§€ μ•Šκ³  `Storage` μΈν„°νŽ˜μ΄μŠ€μ— μ˜μ‘΄ν•œλ‹€. 이λ₯Ό 톡해 `DataManager`의 μ €μž₯ λ©”μ»€λ‹ˆμ¦˜μ„ λ³€κ²½ν•  λ•Œ `DataManager` μ½”λ“œλ₯Ό λ³€κ²½ν•  ν•„μš” 없이,  λ‹€λ₯Έ `Storage` κ΅¬ν˜„μ²΄λ₯Ό μ£Όμž…ν•˜κΈ°λ§Œ ν•˜λ©΄ λœλ‹€.

*️⃣정리

μŠ€ν”„λ§μ€ λ‹€μŒ 기술둜 λ‹€ν˜•μ„± + OCP & DIP λ₯Ό κ°€λŠ₯ν•˜κ²Œ μ§€μ›ν•œλ‹€.

 

DI (Dependency Injection) = μ˜μ‘΄κ΄€κ³„, μ˜μ‘΄μ„± μ£Όμž…
DI μ»¨ν…Œμ΄λ„ˆ 제곡

 

ν΄λΌμ΄μ–ΈνŠΈ μ½”λ“œμ˜ λ³€κ²½ 없이 κΈ°λŠ₯ ν™•μž₯

728x90
Contents

ν¬μŠ€νŒ… μ£Όμ†Œλ₯Ό λ³΅μ‚¬ν–ˆμŠ΅λ‹ˆλ‹€

이 글이 도움이 λ˜μ—ˆλ‹€λ©΄ 곡감 λΆ€νƒλ“œλ¦½λ‹ˆλ‹€.