SOLID๋ ๊ฐ์ฒด์งํฅ ํ๋ก๊ทธ๋๋ฐ ํ๋ฉด์ ์ง์ผ์ผํ๋ 5๋ ์์น์ด๋ค.
๋ฌธ์ | ์ฝ์ด | ๊ฐ๋ |
---|---|---|
S | SRP (Single Responsibility Principle) | ๋จ์ผ ์ฑ
์ ์์น (ํ ํด๋์ค๋ ํ๋์ ์ฑ ์๋ง ๊ฐ์ ธ์ผ ํ๋ค.) |
O | OCP (Open/Closed Priciple) | ๊ฐ๋ฐฉ-ํ์ ์์น (์ํํธ์จ์ด ์์๋ ํ์ฅ์๋ ์ด๋ ค ์์ผ๋ ๋ณ๊ฒฝ์๋ ๋ซํ ์์ด์ผ ํ๋ค.) |
L | LSP (Listov Substitution Priciple) | ๋ฆฌ์ค์ฝํ ์นํ ์์น (ํ๋ก๊ทธ๋จ์ ๊ฐ์ฒด๋ ํ๋ก๊ทธ๋จ์ ์ ํ์ฑ์ ๊นจ๋จ๋ฆฌ์ง ์์ผ๋ฉด์ ํ์ ํ์ ์ ์ธ์คํด์ค๋ก ๋ฐ๊ฟ ์ ์์ด์ผ ํ๋ค.) |
I | ISP (Interface Segregation Principle) | ์ธํฐํ์ด์ค ๋ถ๋ฆฌ ์์น (ํน์ ํด๋ผ์ด์ธํธ๋ฅผ ์ํ ์ธํฐํ์ด์ค ์ฌ๋ฌ ๊ฐ๊ฐ ๋ฒ์ฉ ์ธํฐํ์ด์ค ํ๋๋ณด๋ค ๋ซ๋ค.) |
D | DIP (Dependency Inversion Principle) | ์์กด๊ด๊ณ ์ญ์ ์์น (ํ๋ก๊ทธ๋๋จธ๋ "์ถ์ํ์ ์์กดํด์ผ์ง, ๊ตฌ์ฒดํ์ ์์กดํ๋ฉด ์๋๋ค.") |
- ๊ฐ ํด๋์ค์ ํ๋์ ์ฑ ์๊ณผ ํ๋์ ๋ชฉ์ ์ด ์์ด์ผ ํ๋ค.
// ํ
์คํธ๋ฅผ ๋ณ๊ฒฝํ๋ ์ฝ๋๊ฐ ํฌํจ๋ ํด๋์ค
public class TextManipulator {
private final String text;
public setText(String text) {
this.text = text;
}
public String getText() {
return text;
}
public void appendText(String newText) {
text = text.concat(newText);
}
public String findWordAndReplace(String word, String replacementWord) {
if (text.contains(word)) {
text = text.replace(word, replacementWord);
}
return text;
}
public String findWordAndDelete(String word) {
if (text.contains(word)) {
text = text.replace(word, "");
}
return text;
}
// ** ์ถ๋ ฅ ๋ฉ์๋ **
public void printText() {
System.out.println(textManipulator.getText());
}
}
์์ ์ฝ๋๋ ๊ด์ฐฎ์ ๋ณด์ด์ง๋ง SRP์ ์ข์ ์๋ ์๋๋ค.
์ ์ฝ๋๋ ๋ ๊ฐ์ง ์ฑ
์์ด ์๋ค.
1. ํ
์คํธ ์กฐ์
2. ์ถ๋ ฅ
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์ธ์ ํ ์คํธ๋ง ์ฒ๋ฆฌํ๋ ๋ ๋ค๋ฅธ ํด๋์ค๋ฅผ ๋ง๋ค์ด์ผ ํ๋ค
// ํ
์คํธ ์ถ๋ ฅ ํด๋์ค
public class TextPrinter {
TextManipulator textManipulator;
public TextPrinter(TextManipulator textManipulator) {
this.textManipulator = textManipulator;
}
public void printText() {
System.out.println(textManipulator.getText());
}
public void printOutEachWordOfText() {
System.out.println(Arrays.toString(textManipulator.getText().split(" ")));
}
public void printRangeOfCharacters(int startingIndex, int endIndex) {
System.out.println(textManipulator.getText().substring(startingIndex, endIndex));
}
}
SRP ์์น์ ๋ฐ๋ผ ์ฐ๋ฆฌ ํด๋์ค๋ ํ๋์ ๊ธฐ๋ฅ์ ๊ณ ์ํ๋ค.
TextManipulator ํด๋์ค ๋ฉ์๋๋ก ๋์๊ฐ๋ณด์.
...
public void appendText(String newText) {
text = text.concat(newText);
}
public String findWordAndReplace(String word, String replacementWord) {
if (text.contains(word)) {
text = text.replace(word, replacementWord);
}
return text;
}
public String findWordAndDelete(String word) {
if (text.contains(word)) {
text = text.replace(word, "");
}
return text;
}
...
์ฌ๊ธฐ์ ์ด ํด๋์ค๊ฐ ํ๋ ์ผ์ ๋ํ ๋ช ํํ ํํ์ด ๋์ด ์๋ค. "ํ ์คํธ ์กฐ์."
๊ทธ๋ฌ๋ ์์ง๋ ฅ์ ๋ํด ์๊ฐํ์ง ์๊ณ ์ด ํด๋์ค์ ์ฑ
์์ด ๋ฌด์์ธ์ง์ ๋ํ ๋ช
ํํ ์ ์๊ฐ ์๋ค๋ฉด ํ
์คํธ๋ฅผ ์์ฑํ๊ณ ์
๋ฐ์ดํธํ๋ ๊ฒ์ ์๋ก ๋ค๋ฅธ ๋ณ๊ฐ์ ์์
์ด๋ผ๊ณ ์๊ฐํ ์ ์๋ค.
์ด ์๊ฐ์ ๋ฐ๋ผ ์ฐ๋ฆฌ๋ ์ด๊ฒ์ด ๋ ๊ฐ์ ๋ณ๋ ํด๋์ค์ธ WriteText ๋ฐ UpdateText ์ฌ์ผ ํ๋ค๋ ๊ฒฐ๋ก ์ ๋ด๋ฆด ์ ์์ต๋๋ค .
ํ์ง๋ง ๋ณธ์ง์ ์ผ๋ก ํ ์คํธ ์กฐ์ ์ด๋ผ๋ ๋จ์ผ ๋ชฉ์ ์ ์ํํ๋ค.
- ํ์ฅ์๋ ์ด๋ ค ์๊ณ ๋ณ๊ฒฝ์๋ ๋ซํ ์์ด์ผ ํ๋ค.
โช ์๋ก์ด ํ์ ์ ์ถ๊ฐํจ์ผ๋ก์จ ์๋ก์ด ๊ธฐ๋ฅ์ ์ถ๊ฐ(๊ตฌํ)ํ ์ ์๋ค.ย ๋ฐ๋ผ์ ํ์ฅ์ด ์ด๋ ค์๋ค๋ ๋ง์ ์๋ก์ด ํ์ (ํด๋์ค, ๋ชจ๋, ํจ์)์ ์ถ๊ฐํจ์ผ๋ก์จ ๊ธฐ๋ฅ์ ํ์ฅ์ํค๋ ๊ฒ์ ๋งํ๋ค.
โช ํ์ฅ์ด ๋ฐ์ํ์ ๋ย ์์ ๋ ๋ฒจ์ด ์ํฅ์ย ๋ฏธ์น์ง ์์์ผย ํ๋ ๊ฒ์ ๋งํ๋ค.
๋ฐ๋ผ์ ๋ณ๊ฒฝ์๋ ๋ซํ์์ด์ผ ํ๋ค๋ ๋ง์ ํ์ฅ์ด ๋ฐ์ํ์ ๋ ํด๋น ์ฝ๋๋ฅผ ํธ์ถ ํ๋ ์ชฝ์์ ๋ณ๊ฒฝ์ด ๋ฐ์ํ์ง ์๋ ๊ฒ์ ๋งํ๋ค.
๊ณ๋ฐฉ ํ์ ์์น์ ๊ธฐ์กด ์ฝ๋๋ฅผ ๋ณ๊ฒฝํ์ง ์์ผ๋ฉด์(Close)
๊ธฐ๋ฅ์ ์ถ๊ฐ(Open)ํ ์ ์๋๋ก ์ค๊ณ๊ฐ ๋์ด์ผ ํ๋ค๋ ์์น์ด๋ค.
๋ํ๊ธฐ ๋ฐ ๋นผ๊ธฐ์ ๊ฐ์ ์ฌ๋ฌ ์ฐ์ฐ์ด ์์ ์ ์๋ ๊ณ์ฐ๊ธฐ ์ฑ์ ๋น๋ํ๋ค๊ณ ๊ฐ์ ํด๋ณด์.
// ์ต์์ ์ธํฐํ์ด์ค์ธ CalculatorOperation ๋ฅผ ์ ์
public interface CalculatorOperation {}
// ๋ง์
ํด๋์ค
public class Addition implements CalculatorOperation {
private double left;
private double right;
private double result = 0.0;
public Addition(double left, double right) {
this.left = left;
this.right = right;
}
// getters and setters
}
ํ์ฌ๋ก์จ๋ Addition ํด๋์ค๊ฐ ํ๋๋ง ์์ผ๋ฏ๋ก Subtraction ์ด๋ผ๋ ๋ค๋ฅธ ํด๋์ค๋ฅผ ์ ์ํด์ผ ํ๋ค.
// ๋บ์
ํด๋์ค
public class Subtraction implements CalculatorOperation {
private double left;
private double right;
private double result = 0.0;
public Subtraction(double left, double right) {
this.left = left;
this.right = right;
}
// getters and setters
}
์ด์ ๊ณ์ฐ๊ธฐ ์์ ์ ์ํํ ๊ธฐ๋ณธ ํด๋์ค๋ฅผ ์ ์ํด ๋ณด๊ฒ ๋ค.
public class Calculator {
public void calculate(CalculatorOperation operation) {
if (operation == null) {
throw new InvalidParameterException("Can not perform operation");
}
if (operation instanceof Addition) {
Addition addition = (Addition) operation;
addition.setResult(addition.getLeft() + addition.getRight());
} else if (operation instanceof Subtraction) {
Subtraction subtraction = (Subtraction) operation;
subtraction.setResult(subtraction.getLeft() - subtraction.getRight());
}
}
}
์์ ์ฝ๋๋ ๊ด์ฐฎ์ ๋ณด์ด์ง๋ง OCP์ ์ข์ ์๋ ์๋๋ค.
๊ณฑํ๊ธฐ ๋๋ ๋๋๊ธฐ ๊ธฐ๋ฅ์ ์ถ๊ฐํด์ผ ํ๋ ์๋ก์ด ์๊ตฌ ์ฌํญ์ด ๋ค์ด์ค๋ฉด Calculator ํด๋์ค ์ ๊ณ์ฐ ๋ฐฉ๋ฒ์ ๋ณ๊ฒฝํ๋ ๊ฒ ์ธ์๋ ๋ฐฉ๋ฒ์ด ์๋ค.
๋ฐ๋ผ์ ์ด ์ฝ๋๋ OCP์ ํธํ๋์ง ์๋๋ค๊ณ ๋งํ ์ ์๋ค.
public interface CalculatorOperation {
void perform();
}
public class Addition implements CalculatorOperation {
private double left;
private double right;
private double result;
// constructor, getters and setters
@Override
public void perform() {
result = left + right;
}
}
๋ง์ฐฌ๊ฐ์ง๋ก ๋นผ๊ธฐ ํด๋์ค๋ ๋น์ทํ ๋
ผ๋ฆฌ๋ฅผ ๊ฐ๋๋ค.
์ถ๊ฐ ๋ฐ ๋นผ๊ธฐ ์ ์ ์ฌํ๊ฒ ์๋ก์ด ๋ณ๊ฒฝ ์์ฒญ์ผ๋ก ๋๋๊ธฐ ๋
ผ๋ฆฌ๋ฅผ ๊ตฌํํ ์ ์๋ค.
public class Division implements CalculatorOperation {
private double left;
private double right;
private double result;
// constructor, getters and setters
@Override
public void perform() {
if (right != 0) {
result = left / right;
}
}
}
๋ง์ง๋ง์ผ๋ก Calculator ํด๋์ค๋ ์๋ก์ด ์ฐ์ฐ์๋ฅผ ๋์ ํ ๋ ์๋ก์ด ๋ก์ง์ ๊ตฌํํ ํ์๊ฐ ์๋ค.
public class Calculator {
public void calculate(CalculatorOperation operation) {
if (operation == null) {
throw new InvalidParameterException("Cannot perform operation");
}
operation.perform();
}
}
์ด๋ ๊ฒ ํ๋ฉด ํด๋์ค๋ ์์ ์ ์ํด ๋ซํ๊ณ ํ์ฅ์ ์ํด ์ด๋ฆฐ๋ค.
ํ๋ก๊ทธ๋จ์ ๊ฐ์ฒด๋ ํ๋ก๊ทธ๋จ์ ์ ํ์ฑ์ ๊นจ๋จ๋ฆฌ์ง ์์ผ๋ฉด์ ํ์ ํ์ ์ ์ธ์คํด์ค๋ก ๋ฐ๊ฟ ์ ์์ด์ผ ํ๋ค.
(ํ์ ์ ํ์ ๊ธฐ๋ณธ ์ ํ์ผ๋ก ๋์ฒดํ ์ ์์ด์ผ ํ๋ค.)
LSP ์นํ ์๋ฆฌ๋ฅผ ์ดํดํ๋ ค๋ฉด ๋จผ์ ๊ฐ๋ฐฉ/ํ์ ์๋ฆฌ(SOLID์ "O")๋ฅผ ์ดํดํด์ผ ํ๋ค.
Open/Closed ์์น์ ๋ชฉํ๋ ์ฐ๋ฆฌ๊ฐ ์ํํธ์จ์ด๋ฅผ ์ค๊ณ ํ์ฌ ์๋ก์ด ์ฝ๋๋ฅผ ์ถ๊ฐํจ์ผ๋ก์จ๋ง ์๋ก์ด ๊ธฐ๋ฅ์ ์ถ๊ฐํ๋๋ก ๊ถ์ฅํ๋ค.
์ด๊ฒ์ด ๊ฐ๋ฅํ๋ฉด ๋์จํ๊ฒ ๊ฒฐํฉ๋์ด ์ฝ๊ฒ ์ ์ง ๊ด๋ฆฌํ ์ ์๋ ์์ฉ ํ๋ก๊ทธ๋จ์ด ๋๋ค.
์๋๋ OCP๋ฅผ ์ค์ํ ์ํ ์ฑ ํด๋์ค ๋ค์ด์ด๊ทธ๋จ์ด๋ค.
์์ ํด๋์ค ๋ค์ด์ด๊ทธ๋จ์ ๊ด์ฐฎ์ ๋ณด์ด์ง๋ง LSP์ ์ข์ ์๋ ์๋๋ค.
์ฌ๊ธฐ์์ CurrentAccount ๋ฐ SavingsAccount๊ฐ ํ์ฅํ๋ ์๋ก์ด ์ถ์ Account ํด๋์ค๋ฅผ ๋์ ํ๋ค.
BankingAppWithdrawalService ๋ ๋ ์ด์ ๊ตฌ์ฒด์ ์ธ ๊ณ์ข ํด๋์ค์ ์์กดํ์ง ์๋๋ค.
์ด์ ์ถ์ ํด๋์ค์๋ง ์์กดํ๊ธฐ ๋๋ฌธ์ ์๋ก์ด ๊ณ์ข ์ ํ์ด ๋์
๋ ๋ ๋ณ๊ฒฝํ ํ์๊ฐ ์๋ค.
๊ฒฐ๊ณผ์ ์ผ๋ก BankingAppWithdrawalService๋ ์ ๊ณ์ข ์ ํ์ด ์๋ ํ์ฅ์ ๋ํด ์ด๋ ค ์์ง๋ง ์ ์ ํ์ ํตํฉ์ ์ํด ๋ณ๊ฒฝํ ํ์๊ฐ ์๋ค๋ ์ ์์ ์์ ์ ์ํด ๋ซํ์๋ค.(OCP ์ค์)
์ ์์ ๋ฅผ Java ์ฝ๋๋ก ๋ณด์
๋จผ์ Account ํด๋์ค๋ฅผ ์ ์ํด ๋ณธ๋ค.
public abstract class Account {
protected abstract void deposit(BigDecimal amount);
/**
* Reduces the balance of the account by the specified amount
* provided given amount > 0 and account meets minimum available
* balance criteria.
*
* @param amount
*/
protected abstract void withdraw(BigDecimal amount);
}
๊ทธ๋ฆฌ๊ณ BankingAppWithdrawalService๋ฅผ ์ ์ํด๋ณธ๋ค.
public class BankingAppWithdrawalService {
private Account account;
public BankingAppWithdrawalService(Account account) {
this.account = account;
}
public void withdraw(BigDecimal amount) {
account.withdraw(amount);
}
}
์ด์ ์ ๋์์ธ์ด LSP์ ์์น์ ์ด๋ป๊ฒ ์๋ฐํ๋์ง ์ดํด๋ณด์.
์ํ์ ๊ณ ๊ฐ์๊ฒ ๊ณ ๊ธ๋ฆฌ์ ์ ๊ธฐ์๊ธ์ ์ ๊ณตํ๊ณ ์ ํ๋ค.
์ด๋ฅผ ์ง์ํ๊ธฐ ์ํด FixedTermDepositAccount ํด๋์ค๋ฅผ ๋์
ํ์.
// ์ ๊ธฐ์๊ธ ํด๋์ค
public class FixedTermDepositAccount extends Account {
// Overridden methods...
}
๊ด์ฐฎ์๋ฏํ๋ค.
๊ทธ๋ฌ๋ ์ํ์ ์ ๊ธฐ์๊ธ ๊ณ์ข์ ๋ํ ์ถ๊ธ์ ํ์ฉํ์ง ์๋๋ค.
์ด๋ ๊ณง FixedTermDepositAccount ํด๋์ค๊ฐ Account๊ฐ ์ ์ํ ์ธ์ถ ๋ฐฉ๋ฒ์ ์๋ฏธ ์๊ฒ ์ ๊ณตํ ์ ์์์ ์๋ฏธํ๋ค.
(์ํํ ์ ์๋ ๋ฉ์๋์์ UnsupportedOperationException์ throw ํ๋ ๋ฐฉ๋ฒ์ด ์๊ธด ํ์ง๋ง ์ณ์ ๋ฐฉ๋ฒ์ด ์๋๋ค.)
์์์ FixedTermDepositAccount๋ Account์ ํ์ ์ ํ์ด ์๋๋ค.
๋ชจ๋ ๊ณ์ข ์ ํ์ด ์ถ๊ธ์ ํ์ฉํ๋ค๊ณ ์๋ชป ๊ฐ์ ํ๋ค.
์ถ๊ธ์ ์ง์ํ์ง ์๋ FixedTermDepositAccount๋ฅผ ํฌํจํ Account์ ๋ชจ๋ ํ์ ์ ํ์ ์ถ๊ธ ๋ฐฉ์์ ์์๋ฐ์๋ค.
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ค.
์๋์ ๋ค๋ฅด๊ฒ ์ค๊ณ๋ LSP ์ค์ ํด๋์ค ๋ค์ด์ด๊ทธ๋จ์ ๋ณด์.
๋ชจ๋ ๊ณ์ข๊ฐ ์ธ์ถ์ ์ง์ํ์ง ์๊ธฐ ๋๋ฌธ์ ์ธ์ถ ๋ฉ์๋๋ฅผ Account ํด๋์ค์์ ์๋ก์ด ์ถ์ ํ์ ํด๋์ค WithdrawableAccount๋ก ์ฎ๊ฒผ๋ค.
CurrentAccount์ SavingsAccount ๋ชจ๋ ์ธ์ถ์ ํ์ฉํ๋ค.
๊ทธ๋์ ๊ทธ๊ฒ๋ค์ ์๋ก์ด WithdrawableAccount์ ์๋ธํด๋์ค๊ฐ ๋์๋ค.
๊ทธ๋ฆฌ๊ณ FixedTermDepositAccount๋ ์
๊ธ๋ง ๊ฐ๋ฅํ๊ฒ ๋์๋ค.
๊ทธ๋ฌ๋ฉด BankingAppWithdrawalService๋ ์ด์ WithdrawableAccount๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค.
public class BankingAppWithdrawalService {
private WithdrawableAccount withdrawableAccount;
public BankingAppWithdrawalService(WithdrawableAccount withdrawableAccount) {
this.withdrawableAccount = withdrawableAccount;
}
public void withdraw(BigDecimal amount) {
withdrawableAccount.withdraw(amount);
}
}
ํ์ด์ ์ด ๊ฒ ๋๋ฌด ์ฅํฉํด์ ์ดํดํ๊ธฐ ์ด๋ ค์ธ๋ฏํ์ฌ
์ฌ์ด ์์๋ฅผ ๊ตฌํด์๋ค.
์ณ์ ์์ ex) ๋๋ฌผ ํฅ์ ๊ณ ๋ = new ๊ณ ๋();
์์ ์ณ์ ์์๋ก ๋ณด๋ฉด ๋๋ฌผ์ด๋ผ๋ ์ต์์ ํ์ ์ ํ์์ ๋ชจ๋ ํ์ ์ ๊ต์ฒดํ ์ ์๋ค. ์ด๋ฐ์์ผ๋ก ์, ํ์ ๊ด๊ณ๋ฅผ ๋๋ ๋์๋ ๋ ผ๋ฆฌ์ ์ผ๋ก ๋ง๋ ๊ตฌ์กฐ๋ก ์ค๊ณํ์ฌ ์์ฑํด์ผ ํ๋ค.์ถ์ฒ: https://jeongkyun-it.tistory.com/156 [๋์ ๊ณผ๊ฑฐ์ผ์ง:ํฐ์คํ ๋ฆฌ]
ํน์ ํด๋ผ์ด์ธํธ๋ฅผ ์ํ ์ธํฐํ์ด์ค ์ฌ๋ฌ ๊ฐ๊ฐ ๋ฒ์ฉ ์ธํฐํ์ด์ค ํ๋๋ณด๋ค ๋ซ๋ค.
์ง๋ถ ์ ํ์ ๋ํ ํด๋์ค ๋ค์ด์ด๊ทธ๋จ.
// ๊ฒฐ์ ์ธํฐํ์ด์ค
public interface Payment {
// original methods
...
void intiateLoanSettlement();
void initiateRePayment();
}
public class LoanPayment implements Payment {
@Override
public void initiatePayments() {
throw new UnsupportedOperationException("This is not a bank payment");
}
@Override
public void initiateRePayment() {
// ...
}
@Override
public Object status() {
// ...
}
@Override
public List<Object> getPayments() {
// ...
}
@Override
public void intiateLoanSettlement() {
// ...
}
}
์ด์ Payment ์ธํฐํ์ด์ค๊ฐ ๋ณ๊ฒฝ๋๊ณ ๋ ๋ง์ ๋ฉ์๋๊ฐ ์ถ๊ฐ๋์์ผ๋ฏ๋ก ๋ชจ๋ ๊ตฌํ ํด๋์ค๋ ์ด์ ์ถ๊ฐ๋ ์ ๋ฉ์๋๋ฅผ ๊ตฌํํด์ผ ํ๋ค.
์ ์ฝ๋์์ LoanPayment ๊ตฌํ ํด๋์ค๋ ์ค์ ํ์ ์์ด initialPayments()๋ฅผ ๊ตฌํํด์ผ ํ๋ค.
๋ฐ๋ผ์ BankPayment ํด๋์ค๋ ์ด๋ป๊ฒ ๋ ๊น?
public class BankPayment implements Payment {
@Override
public void initiatePayments() {
// ...
}
@Override
public Object status() {
// ...
}
@Override
public List<Object> getPayments() {
// ...
}
@Override
public void intiateLoanSettlement() {
throw new UnsupportedOperationException("This is not a loan payment");
}
@Override
public void initiateRePayment() {
throw new UnsupportedOperationException("This is not a loan payment");
}
}
์์ ๊ฐ์ ์ฝ๋๊ฐ ๋์ด๋ฒ๋ฆฐ๋ค.
์ ์ฐ๋ ๋ฉ์๋๋ฅผ UnsupportedOperationException์ throwํ ๋ฟ์ด๋ค.
์ด๊ฒ์ ๋ฌธ์ ๋
์ถ๊ฐ๋ ๋ฉ์๋๋ฅผ ๊ตฌํํ๋ ๊ฒ์ด ์์น ์์๋ฐ ๊ฐ์ ์ ์ผ๋ก ๊ตฌํ์ ํด์ผํ๋ค๋ ๊ฒ์ด๋ค. ์ด๋ ๊ณง ๋ง์ ๋ถ์์ฉ์ ์ด๋ํ๋ค.
์ ํด๋์ค ๋ค์ด์ด๊ทธ๋จ์ ๋ณด์.
// ์ธํฐํ์ด์ค
public interface Payment {
Object status();
List<Object> getPayments();
}
๋ ๊ฐ์ง ์ ํ์ ๊ฒฐ์ ๋ฅผ ์ํ ๋ ๊ฐ์ ์ธํฐํ์ด์ค ์ถ๊ฐ
1. ์ฒซ ๋ฒ์งธ ์ธํฐํ์ด์ค
public interface Bank extends Payment {
void initiatePayments();
}
2. ๋ ๋ฒ์งธ ์ธํฐํ์ด์ค
public interface Loan extends Payment {
void intiateLoanSettlement();
void initiateRePayment();
}
๊ฐ์ ๋ BankPayment ๊ตฌํ ํด๋์ค
public class BankPayment implements Bank {
@Override
public void initiatePayments() {
// ...
}
@Override
public Object status() {
// ...
}
@Override
public List<Object> getPayments() {
// ...
}
}
๊ฐ์ ๋ LoanPayment ๊ตฌํ ํด๋์ค
public class LoanPayment implements Loan {
@Override
public void intiateLoanSettlement() {
// ...
}
@Override
public void initiateRePayment() {
// ...
}
@Override
public Object status() {
// ...
}
@Override
public List<Object> getPayments() {
// ...
}
}
ํ๋ก๊ทธ๋๋จธ๋ "์ถ์ํ์ ์์กดํด์ผ์ง, ๊ตฌ์ฒดํ์ ์์กดํ๋ฉด ์๋๋ค."
๋ฐฑ์๋ ๊ฐ๋ฐ์
// ๋ฐฑ์๋ ๊ฐ๋ฐ์
public class BackEndDeveloper {
public void writeJava() {}
}
ํ๋ก ํธ์๋ ๊ฐ๋ฐ์
// ํ๋ก ํธ์๋ ๊ฐ๋ฐ์
public class FrontEndDeveloper {
public void writeJavascript() {}
}
ํ๋ก์ ํธ Class์์ ์์ ๋ ๊ฐ์ง๋ฅผ ๋ชจ๋ ์ฌ์ฉํ๋ค.
public class Project {
private BackEndDeveloper backEndDeveloper = new BackEndDeveloper();
private FrontEndDeveloper frontEndDeveloper = new FrontEndDeveloper();
public void implement() {
backEndDeveloper.writeJava();
frontEndDeveloper.writeJavascript();
}
}
์์ ์ฝ๋๋ ๊ด์ฐฎ์ ๋ณด์ด์ง๋ง DIP์ ์ข์ ์๋ ์๋๋ค.
- ๊ณ ์์ค ๋ชจ๋์ ์ ์์ค ๋ชจ๋์ ์์กดํด์๋ ์ ๋ฉ๋๋ค. ๋ ๋ค ์ถ์ํ์ ์์กดํด์ผ ํฉ๋๋ค.)
- ์ถ์ํ๋ ์ธ๋ถ ์ฌํญ์ ์์กดํด์๋ ์ ๋ฉ๋๋ค. ์ธ๋ถ ์ฌํญ์ ์ถ์ํ์ ๋ฐ๋ผ ๋ฌ๋ผ์ผ ํฉ๋๋ค.)
๋ณด์๋ค์ํผ Project ํด๋์ค๋ ๊ณ ์์ค ๋ชจ๋(์์ ๋ ๋ฒจ ๋ชจ๋)์ด๋ฉฐ BackEndDeveloper ๋ฐ FrontEndDeveloper์ ๊ฐ์ ์ ์์ค ๋ชจ๋(ํ์ ๋ชจ๋)์ ์์กดํ๊ณ ์๋ค.
์์กด๊ด๊ณ ์ญ์ ์์น ์ฒซ ๋ฒ์งธ ๋ถ๋ถ์ ์๋ฐํ๊ณ ์๋ค๋ ๋ป์ด๋ค.
๋ํ Project.class์ implement() ๋ฉ์๋๋ฅผ ๋ณด๋ฉด writeJava()์ writeJavaScript() ๋ฉ์๋๊ฐ ํด๋น ํด๋์ค์ ๋ฐ์ธ๋ฉ๋ ๋ฉ์๋์์ ์ ์ ์๋ค.
ํ๋ก์ ํธ ๋ฒ์์ ๊ดํด์ ๋ ๊ฒฝ์ฐ ๋ชจ๋ ์ธ๋ถ ์ฌํญ์ด๋ค.
์์กด๊ด๊ณ ์ญ์ ์์น ๋ ๋ฒ์งธ ๋ถ๋ถ์ ์๋ฐํ๊ณ ์๋ค๋ ๋ป์ด๋ค.
์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๋ค.
public interface Developer {
void develop();
}
์ถ์ํ๋ฅผ ๋์
ํ์.
๋ฐฑ์๋ ๊ฐ๋ฐ์๋ ๋ค์๊ณผ ๊ฐ์ด ๋ฆฌํฉํฐ๋ง ๋๋ค.
// ๋ฐฑ์๋ ๊ฐ๋ฐ์
public class BackEndDeveloper implements Developer {
@Override
public void develop() {
writeJava();
}
private void writeJava() {
}
}
ํ๋ก ํธ์๋ ๊ฐ๋ฐ์๋ ๋ค์๊ณผ ๊ฐ์ด ๋ฆฌํฉํฐ๋ง ๋๋ค.
// ํ๋ก ํธ์๋ ๊ฐ๋ฐ์
public class FrontEndDeveloper implements Developer {
@Override
public void develop() {
writeJavascript();
}
public void writeJavascript() {
}
}
๋ค์ ๋จ๊ณ๋ ์ฒซ ๋ฒ์งธ ๋ถ๋ถ์ ์๋ฐ์ ํด๊ฒฐํ๊ธฐ ์ํด ํ๋ก์ ํธ ํด๋์ค๋ฅผ ๋ฆฌํฉํฐ๋งํ์ฌ FrontEndDeveloper ๋ฐ BackendDeveloper ํด๋์ค์ ์์กดํ์ง ์๋๋ก ํ๋ ๊ฒ์ด๋ค.
public class Project {
private List<Developer> developers;
public Project(List<Developer> developers) {
this.developers = developers;
}
public void implement() {
developers.forEach(d->d.develop());
}
}
๊ทธ ๊ฒฐ๊ณผ Project ํด๋์ค๋ ํ์ ์ ์์ค ๋ชจ๋์ด ์๋๋ผ ์ถ์ํ์ ์์กดํ๊ฒ ๋๋ค.
๋ํ ๋ฎ์ ์์ค์ ๋ชจ๋๊ณผ ๊ทธ ์ธ๋ถ ์ฌํญ์ ์ถ์ํ์ ์์กดํ๋ค.
์ด๋ ๊ฒ ํ๋ฉด ๋ ๋ฒ์งธ ๋ถ๋ถ์ ์๋ฐ๋ ํด๊ฒฐ์ด ๋๋ค.
๋