JAVA 언어로 배우는 디자인패턴 입문 책의 교재 및 예제 풀이를 정리해보려 한다.
교재는 예제로 특정 문자열의 길이만큼 장식문자 (+, -)를 붙여 출력하는 프로그램을 만든다.
총 사용하는 클래스는 6개로, Display, StringDisplay, Border, SideBorder, FullBorder, Main이다.
동작을 실행시키는 Main 클래스를 제외하고, 추상클래스인 Display 클래스를 부모로 두고, 이를 StringDisplay와 Border가 상속받는 구조이다.
SideBorder 와 FullBorder 는 Border 클래스를 상속받는 자식클래스이다.
Display 클래스에서는 세 개의 추상메소드를 선언하고 show() 메소드를 선언해 모든 행을 표시하도록 한다.
선언하는 추상메소드 세 개는 getColumns, getRows, getRowText 이다.
자세한 내용은 아래의 교재에서 제공하는 사이트를 참고해 예제를 확인하기 바란다.
https://www.youngin.com/reader/pds/pds.asp
만들어야 하는 결과는 아래와 같다.
Hello, world.
-------------
Hello, world.
-------------
*-------------*
*Hello, world.*
*-------------*
+-----------------+
|/////////////////|
||===============||
||*Hello, world.*||
||===============||
|/////////////////|
+-----------------+
이를 위해서 수정할 점은 문저 Main 클래스이다. 새로 생성할 클래스의 이름이 UpDownBorder이고, - 기호가 추가된 모양이므로, FullBorder를 제외한다.
사용하고 싶은 StringDisplay, UpDownDisplay, SidrBorder, FullBorder 에 따라서 아래와 같이 수정한다.
public class Main {
public static void main(String[] args) {
Display b1 = new StringDisplay("Hello, world.");
Display b2 = new UpDownBorder(b1, '-');
Display b3 = new SideBorder(b2, '*');
b1.show();
b2.show();
b3.show();
Display b4 =
new FullBorder(
new UpDownBorder(
new SideBorder(
new UpDownBorder(
new SideBorder(
new StringDisplay("Hello, world."),
'*'
),
'='
),
'|'
),
'/'
)
);
b4.show();
}
}
그리고 새로 만든 UpDownDisplay는 FullBorder와 유사한 모양이되, 장식문자를 지칭하는 것을 생성한다.
private char borderChar; // 장식 문자
// 내용물이 될 Display와 장식 문자를 지정
public UpDownBorder(Display display, char ch) {
super(display);
this.borderChar = ch;
}
...
또한 getRowText부분을 수정해 row가 0일때 또는 row가 getRows() -1 일 때에 해당할 경우의 리턴값과 그렇지 않을 때의 리턴값을 수정해 준다.
...
@Override
public String getRowText(int row) {
if (row == 0 || row == getRows() -1) { // 상단 테두리
return makeLine(borderChar, getColumns());
} else {
return display.getRowText(row - 1) ;
}
}
...
완성해야하는 결과는 아래와 같다.
Hi!
Good morning.
Good night!
#Hi! #
#Good morning.#
#Good night! #
+-------------+
|Hi! |
|Good morning.|
|Good night! |
+-------------+
기존의 클래스에 새로은 클래스를 추가해주는데, 이름은 MultiStringDisplay이다.
출력결과를 보면 space와 데코레이견 기호를 같이 추가해주었다는 것을 알 수 있다.
이를 위해서 기존의 Main 클래스를 수정한다.
public class Main {
public static void main(String[] args) {
MultiStringDisplay md = new MultiStringDisplay();
md.add("Hi!");
md.add("Good mording.");
md.add("Good night!");
md.show();
Display d1 = new SideBorder(md, '#');
d1.show();
Display d2 = new FullBorder(md);
d2.show();
}
}
그리고 MultiStringDisplay 클래스를 수정해주는데, 문자열을 저장하기 위해 리스트와 최대 문자 수를 저장할 변수를 새로 생성한다.
private List<String> body = new ArrayList<>();
private int columns = 0;
각 문자열을 추가받아 최대 문자 수를 갱신하는 add 메소드를 생성하며, 기존의 FullBorder 클래스 처럼 getColumns, getRows, getRowText 를 추가해준다.
@Override
public int getColumns() {
// 문자 수는 내용물 양쪽에 좌우 장식 문자만큼 더한 것
return columns;
}
@Override
public int getRows() {
// 행수는 내용물의 행수에 상하 장식 문자만큼 더한 것
return body.size();
}
@Override
public String getRowText(int row) {
return body.get(row);
}
또한 표시 문자열 오른쪽 끝에 채울 공백을 필요에 따라서 늘려야 하므로 메소드 하나를 추가해준다. 이름은 updatePadding() 이다.
public void updatePadding() {
for (int row = 0; row < body.size(); row++) {
String line = body.get(row);
int padding = columns - line.length();
if (padding > 0) {
body.set(row, line + spaces(padding));
}
}
}
그리고 공백을 만드는 함수를 space라고 하며 count를 인수로 가진다.
private String spaces(int count) {
StringBuilder spaces = new StringBuilder();
for (int i = 0; i < count; i++) {
spaces.append(" ");
}
return spaces.toString();
}