๊ฐ์ฒด ์งํฅ ํ๋ก๊ทธ๋๋ฐ(OOP)์์ ์ํํธ์จ์ด ์ค๊ณ๋ฅผ ๋ ์ดํดํ๊ธฐ ์ฝ๊ณ , ์ ์ฐํ๋ฉฐ, ์ ์ง๋ณด์๊ฐ ์ฉ์ดํ๋๋ก ๋ง๋๋ ๋ค์ฏ ๊ฐ์ง ์์น
SRP๋ฅผ ๋ฐ๋ฅด์ง ์๋ ์์
public class Product {
public void addProduct() {
// ๋ฌผ๊ฑด ์ถ๊ฐ ๋ก์ง
}
public void displayProduct() {
// ๋ฌผ๊ฑด ์ ๋ณด ์ถ๋ ฅ ๋ก์ง
}
}
Product ํด๋์ค๊ฐ ๋ฌผ๊ฑด ์ถ๊ฐ์ ์ ๋ณด ์ถ๋ ฅ ๋ ๊ฐ์ง ์ฑ
์์ ๋ชจ๋ ๋ด๋นSRP๋ฅผ ๋ฐ๋ฅด๋ ์์
public class Product {
public void addProduct() {
// ๋ฌผ๊ฑด ์ถ๊ฐ ๋ก์ง
}
}
public class ProductDisplay {
public void displayProduct(Product product) {
// ๋ฌผ๊ฑด ์ ๋ณด ์ถ๋ ฅ ๋ก์ง
}
}
SRP๋ฅผ ์ค์ํ๋ฉด ํ ๊ธฐ๋ฅ์ ๋ํ ๋ณ๊ฒฝ์ด ๋ค๋ฅธ ๊ธฐ๋ฅ์ ์ํฅ์ ๋ฏธ์น๋ ์ผ์ด ์ค์ด๋ค๊ณ , ์ฝ๋์ ๊ฐ๋ ์ฑ๊ณผ ์ ์ง ๋ณด์์ฑ์ด ํฅ์๋๋ฉฐ, ํ ์คํธํ๊ธฐ๋ ๋ ์ฌ์์ง๋ค.
ํ์ฅ์ ๋ํด์๋ ๊ฐ๋ฐฉ์ (Open)์ด๊ณ , ์์ ์ ๋ํด์๋ ํ์์ (closed)์ด์ด์ผ ํ๋ค.
OCP๋ฅผ ๋ฐ๋ฅด์ง ์๋ ์์
class Shape {
private String type;
public Shape(String type) {
this.type = type;
}
public void draw() {
if (type.equals("circle")) {
drawCircle();
} else if (type.equals("rectangle")) {
drawRectangle();
}
}
private void drawCircle() {
System.out.println("์์ ๊ทธ๋ฆฝ๋๋ค.");
}
private void drawRectangle() {
System.out.println("์ฌ๊ฐํ์ ๊ทธ๋ฆฝ๋๋ค.");
}
}
draw ๋ฉ์๋()๋ฅผ ์์ -> ๊ธฐ์กด ์ฝ๋๋ฅผ ์์ ํด์ผํ๋ฏ๋ก OCP ์๋ฐOCP๋ฅผ ๋ฐ๋ฅด๋ ์์
interface Shape {
void draw();
}
class Circle implements Shape {
public void draw() {
System.out.println("์์ ๊ทธ๋ฆฝ๋๋ค.");
}
}
class Rectangle implements Shape {
public void draw() {
System.out.println("์ฌ๊ฐํ์ ๊ทธ๋ฆฝ๋๋ค.");
}
}
// ์๋ก์ด ๋ํ์ ์ถ๊ฐํด๋ ๊ธฐ์กด ์ฝ๋ ์์ ์์ด ํ์ฅ ๊ฐ๋ฅ!
class Triangle implements Shape {
public void draw() {
System.out.println("์ผ๊ฐํ์ ๊ทธ๋ฆฝ๋๋ค.");
}
}
๋ถ๋ชจ ๊ฐ์ฒด์ ์์ ๊ฐ์ฒด๊ฐ ์์ ๋ ๋ถ๋ชจ ๊ฐ์ฒด๋ฅผ ํธ์ถํ๋ ๋์์์ ์์ ๊ฐ์ฒด๊ฐ ๋ถ๋ชจ ๊ฐ์ฒด๋ฅผ ์์ ํ ๋์ฒดํ ์ ์๋ค๋ ์์น
LSP๋ฅผ ์๋ฐํ ์์
// ๋ถ๋ชจ ํด๋์ค: Rectangle(์ง์ฌ๊ฐํ)
class Rectangle {
protected int width;
protected int height;
public void setWidth(int width) {
this.width = width;
}
public void setHeight(int height) {
this.height = height;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public int getArea() {
return width * height;
}
}
// ์์ ํด๋์ค: Square (์ ์ฌ๊ฐํ)
// Rectangle์ ์์ํ๋ฉด์, ์ ์ฌ๊ฐํ์ ํน์ฑ(๋๋น์ ๋์ด๊ฐ ํญ์ ๋์ผ)์ ๊ฐ์ ํ๊ธฐ ์ํด ์ค๋ฒ๋ผ์ด๋ฉ ํจ
class Square extends Rectangle {
@Override
public void setWidth(int width) {
super.setWidth(width);
super.setHeight(width); // ๋๋น๊ฐ ๋ฐ๋๋ฉด ๋์ด๋ ๋ณ๊ฒฝ
}
@Override
public void setHeight(int height) {
super.setWidth(height); // ๋์ด๊ฐ ๋ฐ๋๋ฉด ๋๋น๋ ๋ณ๊ฒฝ
super.setHeight(height);
}
}
public class Main {
public static void main(String[] args) {
Rectangle rectangle = new Rectangle();
rectangle.setHeight(5);
rectangle.setWidth(10);
System.out.println(rectangle.getArea());
// --------------------------------------
Rectangle square = new Square();
square.setHeight(5);
square.setWidth(10);
System.out.println(square.getArea());
}
}
50
25
๋ฆฌ์ค์ฝํ ์นํ ์์น์ ๋ถ๋ชจ ๊ฐ์ฒด๋ฅผ ํธ์ถํ๋ ๋์์์ ์์ ๊ฐ์ฒด๊ฐ ๋ถ๋ชจ ๊ฐ์ฒด๋ฅผ ์์ ํ ๋์ฒด ํ ์ ์๋ค๋ ์์น -> ๊ฐ์ ๊ฐ์ด ๋์์ผํจRectangle์ฒ๋ผ ๋์ํ ๊ฒ์ผ๋ก ๊ธฐ๋ํ์ง๋ง, Square๋ ๋ด๋ถ์ ์ผ๋ก ์ ์ฌ๊ฐํ์ ์ ์ฝ ์กฐ๊ฑด์ ์ ์ฉํด ์๋์ ๋ค๋ฅธ ๊ฒฐ๊ณผ๊ฐ ๋์ค๋ ๊ฒ๐ฅ ์ด๋ ๋ฐ๋ก ์ ์ฌ๊ฐํ์ด ์ง์ฌ๊ฐํ์ ์์ ๋ฐ๋ ๊ฒ์ด ์ฌ๋ฐ๋ฅธ ์์ ๊ด๊ณ๊ฐ ์๋๋ผ๋ ๊ฒ์ ์๋ฏธ! ์์ ๊ฐ์ฒด๊ฐ ๋ถ๋ชจ ๊ฐ์ฒด์ ์ญํ ์ ์์ ํ ๋์ฒดํ์ง ๋ชปํ๋ค๋ ์๋ฏธํ๋ค.
LSP๋ฅผ ์ ์ฉ ์์
public class Shape {
public int width;
public int height;
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public int getArea() {
return width * height;
}
}
//์ง์ฌ๊ฐํ ํด๋์ค
public class Rectangle extends Shape {
public Rectangle(int width, int height) {
setWidth(width);
setHeight(height);
}
}
//์ ์ฌ๊ฐํ ํด๋์ค
public class Square extends Shape{
public Square(int length) {
setWidth(length);
setHeight(length);
}
}
public class Main {
public static void main(String[] args) {
Shape rectangle = new Rectangle(10, 5);
Shape square = new Square(5);
System.out.println(rectangle.getArea());
System.out.println(square.getArea());
}
}
50
25
์ฒซ๋ฒ์งธ์ ์ง์ฌ๊ฐํ ํด๋์ค๋ฅผ ์์๋ฐ์ ์ ์ฌ๊ฐํ ๊ฐ์ฒด ์์ ์ฒ๋ผ, ์ฌ๋ฐ๋ฅด์ง ๋ชปํ ์์๊ด๊ณ๋ ์ ๊ฑฐํ๊ณ ๋ถ๋ชจ ๊ฐ์ฒด์ ๋์์ ์๋ฒฝํ ๋์ฒดํ ์ ์๋ ๊ด๊ณ๋ง ์์ํ๋๋ก ์ฝ๋๋ฅผ ์ค๊ณ
- ๊ฐ์ฒด๋ ์์ ์ด ์ฌ์ฉํ๋ ๋ฉ์๋์๋ง ์์กดํด์ผ ํ๋ค๋ ๋ฒ์น
- ๊ฐ์ฒด๊ฐ ์ฌ์ฉํ์ง ์๋ ๋ฉ์๋๋ฅผ ์์กดํด์๋ ์ ๋๋ค๋ ๋ป
ISP๋ฅผ ์๋ฐํ ์์
interface Employee {
void work();
void eat();
}
class HumanEmployee implements Employee {
@Override
public void work() {
// ์์
ํ๋ ์ฝ๋
}
@Override
public void eat() {
// ์์ฌํ๋ ์ฝ๋
}
}
class AIEmployee implements Employee {
@Override
public void work() {
// ์์
ํ๋ ์ฝ๋
}
@Override
public void eat() {
// AI์ ๋จน์ง ์์ง๋ง ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํด์ผ ํจ
throw new UnsupportedOperationException("๋ก๋ด์ ๋จน์ง ์์ต๋๋ค.");
}
}
ISP ์ ์ฉ ์์
// ์์
ํ๋ ๊ธฐ๋ฅ์ ์ ์ํ ์ธํฐํ์ด์ค
interface Workable {
void work();
}
// ์์ฌํ๋ ๊ธฐ๋ฅ์ ์ ์ํ ์ธํฐํ์ด์ค
interface Eatable {
void eat();
}
class HumanEmployee implements Workable, Eatable {
@Override
public void work() {
// ์์
ํ๋ ์ฝ๋
}
@Override
public void eat() {
// ์์ฌํ๋ ์ฝ๋
}
}
class AIEmployee implements Workable {
@Override
public void work() {
// ์์
ํ๋ ์ฝ๋
}
}
ISP๋ฅผ ์ค์ํ๊ฒ ๋๋ค.
- ๊ณ ์์ค ๋ชจ๋์ ์ ์์ค ๋ชจ๋์ ๊ตฌํ์ ์์กดํด์๋ ์ ๋๋ค.
- ๊ตฌ์ฒดํ์ ์์กดํ์ง ๋ง๊ณ , ์ถ์ํ์ ์์กดํด๋ผ.
-> ์์ ๋ณด๋ค ๋ณํ๊ธฐ ์ฌ์ด ๊ฒ์ ์์กดํ์ง ๋ง๋ผ
DIP ์๋ฐ ์์
public class Driver {
private Lamborghini car;
public void setLamborghini(Lamborghini car) {
this.lamborghini = car;
}
public void drive() {
System.out.println(car.toString());
}
}
public class Main {
public static void main(String[] args) {
Lamborghini myLamborghini = new Lamborghini();
Driver driver = new Driver();
driver.setLamborghini(myLamborghini);
driver.drive();
}
}
Driver๋ ๋๋ณด๋ฅด๊ธฐ๋๋ผ๋ ๊ตฌ์ฒด์ ์ธ ๊ฐ์ฒด์ ์์กดํ๊ณ ์๋ค. ์ด ๊ฒฝ์ฐ ์ด์ ์๊ฐ ์ด์ ํ๋ ์๋์ฐจ์ ์ข
๋ฅ๊ฐ ๋ณ๊ฒฝ๋ ๋, ๋ค์๊ณผ ๊ฐ์ด Driver ํด๋์ค๋ฅผ ์์ ํด์ผํ๋ค.public class Driver {
private Lamborghini car;
private Ferrari car
// ์ด์ ์๊ฐ ์ด์ ํ๋ ์๋์ฐจ ๋ธ๋๋ ์ข
๋ฅ๋งํผ Driver ํด๋์ค ๋ด์ ๋ฉ์๋๊ฐ ์กด์ฌํด์ผํจ.
public void setLamborghini(Lamborghini car) {
this.lamborghini = car;
}
public void setLamborghini(Ferrari car) {
this.Ferrari = car;
}
public void drive() {
System.out.println(car.toString());
}
}
DIP ์ ์ฉ ์์
// Car ์ธํฐํ์ด์ค: ์ถ์ํ ๊ณ์ธต์ ์ ์
public interface Car {
String toString();
}
// Driver ํด๋์ค๋ ๊ตฌ์ฒด์ ์ธ ์๋์ฐจ ๋์ ์ถ์ํ๋ Car์ ์์กดํจ
public class Driver {
private Car car;
public void setCar(Car car) {
this.car = car;
}
public void drive() {
System.out.println(car.toString());
}
}
// Lamborghini ํด๋์ค๋ Car ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํ
public class Lamborghini implements Car {
@Override
public String toString() {
return "Lamborghini car";
}
}
// Ferrari ํด๋์ค๋ Car ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํ
public class Ferrari implements Car {
@Override
public String toString() {
return "Ferrari car";
}
}
public class Main {
public static void main(String[] args) {
// Ferrari ์๋์ฐจ๋ฅผ ์ฌ์ฉํ ์์
Car myFerrari = new Ferrari();
Driver driver = new Driver();
driver.setCar(myFerrari);
driver.drive();
// Lamborghini ์๋์ฐจ๋ฅผ ์ฌ์ฉํ ์์
Car myLamborghini = new Lamborghini();
driver.setCar(myLamborghini);
driver.drive();
}
}
Driverํด๋์ค๋ ์ฝ๋์ ์ด๋ ํ ๋ณํ๋ ์ผ์ด๋์ง ์๊ณ , ์ด๋ ํ ์ํฅ๋ ๋ฏธ์น์ง ์๋๋ค. | ํน์ง | OCP (Open-Closed Principle) | DIP (Dependency Inversion Principle) |
|---|---|---|
| ๋ชฉ์ | ๊ธฐ๋ฅ ํ์ฅ์ ํ์ฉํ๋ ๊ธฐ์กด ์ฝ๋๋ ์์ ํ์ง ์์ | ์์ ๋ชจ๋์ด ํ์ ๋ชจ๋์ ์ง์ ์์กดํ์ง ์๊ณ ์ถ์ํ์ ์์กด |
| ์ด์ | ์ฝ๋ ๋ณ๊ฒฝ ์์ด ํ์ฅ ๊ฐ๋ฅํ ๊ตฌ์กฐ ์ค๊ณ | ๋ชจ๋ ๊ฐ ๊ฒฐํฉ๋๋ฅผ ๋ฎ์ถ๊ณ ์ ์ฐ์ฑ๊ณผ ํ ์คํธ ์ฉ์ด์ฑ์ ํ๋ณด |
| ๋ฐฉ๋ฒ | ๋คํ์ฑ๊ณผ ์ธํฐํ์ด์ค๋ฅผ ํ์ฉํ์ฌ ํ์ฅ ๊ฐ๋ฅํ๋๋ก ์ค๊ณ | ์ธํฐํ์ด์ค๋ ์ถ์ ํด๋์ค๋ฅผ ํตํด ์์กด์ฑ ์ญ์ ๊ตฌํ |
| ์ ์ฉ ๋ฒ์ | ๊ฐ๋ณ ํด๋์ค/๋ชจ๋ ์์ค | ์ฌ๋ฌ ๋ชจ๋ ๊ฐ ๊ด๊ณ ๋ฐ ์์กด์ฑ ๊ด๋ฆฌ |
| ์์ | ์๋ก์ด ๊ธฐ๋ฅ ์ถ๊ฐ ์ ๊ธฐ์กด ํด๋์ค ๋์ ์๋ก์ด ํด๋์ค๋ฅผ ์์ฑ | ์ธํฐํ์ด์ค๋ฅผ ํตํด ์์/ํ์ ๋ชจ๋ ๊ฐ ๊ฒฐํฉ๋๋ฅผ ๋ฎ์ถค |
์ฐธ๊ณ :