목록
- Single Responsibility Principle 단일 책임 원칙
- Open-Closed Principle 개방-폐쇄 원칙
- Liskov Substitution Principle 리스코프 치환 원칙
- Interface Segregation Principle 인터페이스 분리 원칙
- Dependency Inversion Principle 의존 역전 원칙
- 단일 책임의 원칙
1) 클래스는 하나의 책임(역할)만 가져야 한다.
2) 변경의 이유가 하나뿐이어야 한다.
클래스
package Single;
public class EmailService {
// 단일 책임 원칙을 적용한 클래스
public void sendEmail(String email) {
System.out.println("Email send to: " +email);
} // end of sendEmail()
} // end of class
package Single;
public class UserService {
// 단일 책임 원칙을 적용한 클래스
public void createUser(String name) {
System.out.println("User Created: " +name);
} // end of createUser()
} // end of class
실행
package Single;
public class SingleTest {
public static void main(String[] args) {
UserService us = new UserService();
us.createUser("고구마");
EmailService es = new EmailService();
es.sendEmail("이 문자가 들어갈까요?");
} // end of main
} // end of class
실행 결과

- 개방-폐쇄 원칙
1) 소프트웨어 확장에는 열려있고, 수정에는 닫혀 있어야 한다.
2) 기존 코드를 수정하지 않고도 기능을 확장할 수 있어야 한다.
인터페이스
package Open;
public interface Payment {
// 개방-폐쇄 원칙을 적용한 코드
public void process();
} // end of interface
클래스
package Open;
public class PayPalPayment implements Payment{
// 개방-폐쇄 원칙을 적용한 코드
@Override
public void process() {
System.out.println("페이팔 결제 시스템");
}
} // end of class
package Open;
public class CreditCardPayment implements Payment {
// 개방-폐쇄 원칙을 적용한 코드
@Override
public void process() {
System.out.println("신용카드 결제 시스템");
}
}
package Open;
public class KakaoPayPayment implements Payment {
@Override
public void process() {
System.out.println("카카오 결제 시스템");
}
} // end of class
팩토리 클래스
package Open;
public class PaymentFactory {
public static Payment getPayment (String type) {
if(type.equalsIgnoreCase("credit")) {
return new CreditCardPayment();
} else if(type.equalsIgnoreCase("paypal")) {
return new PayPalPayment();
} else if(type.equalsIgnoreCase("kakao")) {
return new KakaoPayPayment();
}
throw new IllegalArgumentException("Invaild payment type: " + type);
} // end of getPayment
} // end of class
실행
package Open;
public class OpenTest {
private Payment payment;
public OpenTest(Payment payment) {
this.payment = payment;
} // end of 생성자
// 결제 프로세스 진행
public void processPayment() {
payment.process();
} // // 주입된 객체의 process() 실행
public static void main(String[] args) {
Payment payment1 = PaymentFactory.getPayment("credit");
payment1.process();
Payment payment2 = PaymentFactory.getPayment("paypal");
payment2.process();
Payment payment3 = PaymentFactory.getPayment("kakao");
payment3.process();
} // end of main
} // end of class
실행 결과

- 리스코프 치환 원칙
1) 자식 클래스는 부모 클래스를 대체할 수 있어야 한다.
2) 즉, 부모 클래스에서 정의한 기능이 자식 클래스에서도 동일하게 동작해야 한다.
추상적
package Liskov;
public abstract class Bird {
public abstract void move();
} // end of class
클래스
package Liskov;
public class FlyingBird extends Bird {
@Override
public void move() {
System.out.println("하늘을 날아서 이동");
} // end of move()
} // end of class
package Liskov;
public class Penguin extends Bird {
@Override
public void move() {
System.out.println("수영해서 이동");
} // end of move()
} // end of class
실행
package Liskov;
public class LiskovTest {
public static void main(String[] args) {
FlyingBird FB = new FlyingBird();
FB.move();
Penguin Pg = new Penguin();
Pg.move();
} // end of main
} // end of class
실행 결과

- 인터페이스 분리 원칙
1) 클라이언트는 자신이 사용하지 않는 메서드에 의존하지 않아야 한다.
2) 여러 작은 인터페이스가 하나의 큰 인터페이스보다 낫다.
인터페이스
package Interface;
public interface Eatable {
public void eat();
}
package Interface;
public interface Workable {
public void work();
}
클래스
package Interface;
public class Human implements Workable, Eatable{
@Override
public void work() {
System.out.println("Human Working");
} // end of work()
public void eat() {
System.out.println("Human eating");
} // end of eat()
} // end of class Human
package Interface;
public class Robot implements Workable {
@Override
public void work() {
System.out.println("Robot working");
}
} // end of Robot
실행
package Interface;
public class InterfaceTest {
public static void main(String[] args) {
Workable wa1 = new Human();
Workable wa2 = new Robot();
wa1.work();
wa2.work();
Eatable ea1 = new Human();
ea1.eat();
} // end of main
} // end of class
실행 결과

- 의존 역전 원칙
1) 고수준 모듈이 저수준 모듈에 의존해서는 안 된다.
2) 추상화된 인터페이스에 의존해야 한다.
고수준 모듈 : 인터페이스(Interface)나 추상(Abstract) 클래스 저수준 모듈 : 메인클래스나 객체
--> 추상화에 의존해야지 구체화에 의존하면 안된다 의미이다.
인터페이스
package Dependency;
public interface InputDevice {
String getInput();
}
클래스
package Dependency;
public class Keyboard implements InputDevice {
@Override
public String getInput() {
return "키보드 입력";
}
}
package Dependency;
public class Mouse implements InputDevice {
@Override
public String getInput() {
return "마우스 입력";
}
}
package Dependency;
public class Computer {
private InputDevice inputDevice;
public Computer(InputDevice inputDevice) {
this.inputDevice = inputDevice;
}
public void userInputDevice() {
System.out.println(inputDevice.getInput());
}
}
실행
package Dependency;
public class DependencyTest {
public static void main(String[] args) {
InputDevice keyboard = new Keyboard();
InputDevice mouse = new Mouse();
Computer computerKeyboard = new Computer(keyboard);
computerKeyboard.userInputDevice();
Computer computerMouse = new Computer(mouse);
computerMouse.userInputDevice();
}
}
실행 결과
