- 객체 생성 방법을 추상화 하기 위한 패턴
- 상황에 맞는 적절한 객체 생성으로 효율성 제고
필수 매개변수만 받는 생성자
필수 매개변수 + 선택 매개변수 1개 생성자
필수 매개변수 + 선택 매개변수 2개 생성자
public class Member {
// 필수값
private String name;
private int age;
// 선택값
private String tel;
private String address;
private String hobby;
private String birthDate;
// 필수값 생성자
private Member(String name, int age) {
this.name = name;
this.age = age;
}
// 생성자를 private으로. (Builder에서는 호출 가능)
private Member(Builder builder) {
this.name = builder.name;
this.age = builder.age;
this.tel = builder.tel;
this.address = builder.address;
this.hobby = builder.hobby;
this.birthDate = builder.birthDate;
}
// 내부 Builder 클래스
public static class Builder {
// 필수값
private String name;
private int age;
// 선택값
private String tel;
private String address;
private String hobby;
private String birthDate;
// Builder 생성자
public Builder(String name, int age) {
this.name = name;
this.age = age;
}
// 선택값 초기화를 위한 메서드들
public Builder tel(String tel) {
this.tel = tel;
return this;
}
public Builder address(String address) {
this.address = address;
return this;
}
public Builder hobby(String builder) {
this.hobby = hobby;
return this;
}
public Builder birthDate(String birthDate) {
this.birthDate = birthDate;
return this;
}
// Builder객체를 이용하여 Member객체 생성하기
public Member build() {
return new Member(this);
}
} // class Builder
} // class Member
public class BuilderPatternDemo {
public static void main(String[] args) {
// ★ 객체 생성시에만 정보를 저장할 수 있다.
// ★ 값을 변경할 수 있는 메서드는 따로 제공되지 않는다
// ==> 1. immutable 객체
// ==> 2. read만 가능하기 때문에 동기화 필요 x
// ==> 3. thread 안전한 멀티스레드 프로그래밍 가능
Member member = new Member
.Builder("홍길동", 18) /*필수값*/
.birthDate("2000-03-22") /*메서드체이닝*/
.hobby("독서")
.build();
// 코드 가독성 ↑
}
}
public interface Shape {
void draw();
}
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("직사각형");
}
}
public class Square implements Shape {
@Override
public void draw() {
System.out.println("정사각형");
}
}
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("원");
}
}
public class ShapeFactory {
public Shape getShape(String shapeType) {
if(shapeType == null) {
return null;
}
if(shapeType.equalsIgnoreCase("CIRCLE")) {
return new Circle();
}
if(shapeType.equalsIgnoreCase("RECTANGLE")) {
return new Rectangle();
}
if(shapeType.equalsIgnoreCase("SQUARE")) {
return new Square();
}
}
}
public class FactoryPatternDemo {
public static void main(String[] args) {
ShapeFactory factory = new ShapeFactory();
Shape shape1 = factory.getShape("CIRCLE");
shape1.draw();
Shape shape2 = factory.getShape("RECTANGLE");
shape2.draw();
Shape shape3 = factory.getShape("SQUARE");
shape3.draw();
}
}
더 큰 구조 또는 새로운 기능을 형성하기 위해 어떻게 클래스 및 객체를 합성하는가와 관련된 패턴
public interface Shape {
void draw();
}
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("직사각형");
}
}
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("원");
}
}
public abstract class ShapeDecorator implements Shape {
/*
* abstract: 인터페이스 Shape의 draw()를 구현하지 않았기때문
* - 이 클래스를 가지고 객체를 안 만들겠다는 의미
* - 객체를 만드려면 '어떤 식으로 만들겠다'가 미리 정의되어야 하는데
* - abstract는 명시적으로 '나는 미완성 클래스'라고 컴파일러에게 알려주는 효과가 있기때문.
*/
protected Shape decoratedShape;
public ShapeDecorator(Shape decoratedShape) {
this.decoratedShape = decoratedShape();
}
}
public class RedShapeDecorator extends ShapeDecorator {
public RedShapeDecorator(Shape decoratedShape) {
super(decoratedShape); // default 생성자 아님 -> super 필수
}
@Override
public void draw() {
decoratedShape.draw(); // 원래 기능: (≒ 기반스트림)
setRedBoarder(decoratedShape); // 새로운 기능
}
// 추가된 기능: 빨간 테두리
private void setRedBorder(Shape decoratedShape) {
System.out.println("빨간색 경계선 칠하기");
}
}
public class DecoratorPatternDemo {
public static void main(String[] args) {
Shape circle = new Circle();
Shape redCircle = new RedShapeDecorator(new Circle());
Shape redRectangle = new RedShapeDecorator(new Rectangle());
System.out.println("< 일반적인 원 그리기 >");
circle.draw();
System.out.println("----------------------------");
System.out.println("< 빨간색 경계선 가진 원 그리기 >");
redCircle.draw();
System.out.println("----------------------------");
System.out.println("< 빨간색 경계선 가진 직사각형 그리기 >");
redRectangle.draw();
}
}
public interface Shape {
void draw();
}
public class Circle implements Shape{
@Override
public void draw() {
System.out.println("Circle: draw()");
}
}
public class Rectangle implements Shape{
@Override
public void draw() {
System.out.println("Rectangle: draw()");
}
}
public class Square implements Shape{
@Override
public void draw() {
System.out.println("Square: draw()");
}
}
public class ShapeMaker {
private Shape circle;
private Shape rectangle;
private Shape square;
public ShapeMaker() {
circle = new Circle();
rectangle = new Rectangle();
square = new Square();
}
public void drawCircle() {
circle.draw();
}
public void drawRectangle() {
rectangle.draw();
}
public void drawSquare() {
square.draw();
}
}
public class FacadePatternDemo {
public static void main(String[] args) {
ShapeMaker shapeMaker = new ShapeMaker();
shapeMaker.drawCircle();
shapeMaker.drawRectangle();
shapeMaker.drawSquare();
}
}
Circle: draw()
Rectangle: draw()
Square: draw()
- 어떤 처리의 책임을 어느 객체에 할당하는 것이 좋은지, 알고리즘을 어느 객체에 정의하는 것이 좋은지 등을 다루는 패턴
- 객체 관점이기 때문에 런타임에 포커스가 많이 맞춰져있음
public interface Strategy {
public int doOperation(int num1, int num2);
}
public class OperationAdd implements Strategy{
@Override
public int doOperation(int num1, int num2) {
return num1 + num2;
}
}
public class OperationSubstract implements Strategy{
@Override
public int doOperation(int num1, int num2) {
return num1 >= num2 ? num1 - num2 : num2 - num1;
}
}
public class OperationMultiply implements Strategy{
@Override
public int doOperation(int num1, int num2) {
return num1 * num2;
}
}
public class OperationCustom implements Strategy{
@Override
public int doOperation(int num1, int num2) {
return num1*num2+num2/num1-num2*num2;
}
}
public class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public int exectue(int num1, int num2) {
return strategy.doOperation(num1, num2);
}
}
public class StrategyPatternDemo {
public static void main(String[] args) {
Context context = new Context(new OperationAdd()); // Context객체 생성시 strategy를 매개변수로 넣어줌
System.out.println("10 + 5 = " + context.execute(10, 5));
context = new Context(new OperationSubstract());
System.out.println("10 - 5 = " + context.execute(10, 5));
context = new Context(new OperationMultiply());
System.out.println("10 * 5 = " + context.execute(10, 5));
context = new Context(new OperationCustom());
System.out.println("10 내맘대로연산 20 = " + context.execute(10, 20));
}
}
public abstract class Game {
abstract void initialize();
abstract void startPlay();
abstract void endPlay();
// template method: defined way(s)/template(s) to execute its methods.
public final void play() {
// initialize the game
initialize();
// start game
startPlay();
// end game
endPlay();
}
}
public class Cricket extends Game{
@Override
void initialize() {
System.out.println("Cricket Game Initialized! Start Playing.");
}
@Override
void startPlay() {
System.out.println("Cricket Game Started. Enjoy the game!");
}
@Override
void endPlay() {
System.out.println("Cricket Game Finished.");
}
}
public class Football extends Game{
@Override
void initialize() {
System.out.println("Football Game Initialized! Start Playing.");
}
@Override
void startPlay() {
System.out.println("Football Game Started. Enjoy the game!");
}
@Override
void endPlay() {
System.out.println("Football Game Finished.");
}
}
public class TemplatePatternDemo {
public static void main(String[] args) {
Game game = new Cricket();
game.play();
System.out.println();
Game game2 = new Football();
game2.play();
}
}
Cricket Game Initialized! Start Playing.
Cricket Game Started. Enjoy the game!
Cricket Game Finished.
Football Game Initialized! Start Playing.
Football Game Started. Enjoy the game!
Football Game Finished.