Chapter 8-2
๋ฐ์ดํ„ฐ ์ฒด๊ณ„ํ™”
- JuL-
๋งˆ๋ฒ• ์ˆซ์ž๋ฅผ ๊ธฐํ˜ธ ์ƒ์ˆ˜๋กœ ์ „ํ™˜
(Replace Magic Number with Symbolic Constant)
โ€ข ๋งˆ๋ฒ• ์ˆซ์ž๋Š” ํŠน์ˆ˜ํ•œ ๊ฐ’์„ ๊ฐ–๋Š” ์ˆซ์ž๋ฅผ ์ผ์ปซ๋Š” ์šฉ์–ด๋กœ , ์—ฌ๋Ÿฌ ๊ณณ์—์„œ ๋…ผ๋ฆฌ์ ์œผ๋กœ ๊ฐ™์€
์ˆซ์ž๋ฅผ ์ฐธ์กฐํ•ด์•ผ ํ•  ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์€๋ฐ , ์ˆ˜์ •ํ•ด์•ผ ํ•  ์ƒํ™ฉ์ด ์˜ค๋ฉด ๋”์ฐํ•œ ์ผ์ด ๋ฐœ์ƒํ•œ๋‹ค .
โ€ข ์ฆ‰ , ์ƒ์ˆ˜๋ฅผ ํ•˜๋“œ์ฝ”๋”ฉํ•˜์ง€ ๋ง์ž .
class TestA{
public boolean isOverFlow(int curCount){
if(curCount > 10){
return true;
}
return false;
}
}
class TestB{
public int getMaxCount(){
return 10;
}
}
class TestA{
public boolean isOverFlow(int curCount){
if(curCount >
CommonConst.MAX_COUNT){
return true;
}
return false;
}
}
class TestB{
public int getMaxCount(){
return CommonConst.MAX_COUNT;
}
}
interface CommonConst{
public int MAX_COUNT = 10;
}
ํ•„๋“œ ์บก์Аํ™”
(Encapsulate Field)
โ€ข ๋ฐ์ดํ„ฐ๋Š” ์ ˆ๋Œ€๋กœ public ์œผ๋กœ ์„ ์–ธํ•˜๋ฉด ์•ˆ๋œ๋‹ค . ๋ฐ˜๋“œ์‹œ private ํ˜•ํƒœ์—์„œ setter,
getter ๋ฅผ๋งŒ๋“ค์–ด ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค .
โ€ข ์–ผํ• ์ƒ๊ฐํ•˜๊ธฐ์—” , publi ์œผ๋กœ ํ•˜๋“  , setter, getter ๋ฅผ ๋งŒ๋“ค๋“  ์™ธ๋ถ€์—์„œ ๊ฐ’์„ ๋ณ€๊ฒฝํ•  ์ˆ˜
์žˆ๋Š” ๊ฒƒ์€ ๋งคํ•œ๊ฐ€์ง€ ์•„๋‹Œ๊ฐ€ ๋ผ๊ณ  ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ์ง€๋งŒ , ์‹ค์ œ ์ฝ”๋”ฉ์„ ํ•ด๋ณด๋ฉด ๊ทธ๋ ‡์ง€ ์•Š๋‹ค
๋Š” ๊ฒƒ์„ ๋А๋‚„ ์ˆ˜ ์žˆ๋‹ค . ์˜ˆ๋ฅผ ๋“ค์–ด , ์•„๋ž˜์™€ ๊ฐ™์€ ์‚ฌ์†Œํ•œ ์‹ค์ˆ˜๋ฅผ ๋ฏธ์—ฐ์— ๋ฐฉ์ง€ํ•  ์ˆ˜๋„ ์žˆ
๊ณ  , ๋ฌด์—‡๋ณด๋‹ค ๋ณ€์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๊ฑฐ๋‚˜ ์„ธํŒ…ํ•  ๋•Œ ์ผ๊ด„ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•  ์ฝ”๋“œ๊ฐ€ ์ถ”๊ฐ€๋  ๊ฒฝ์šฐ ํ•ด
๋‹น ๋ณ€์ˆ˜์˜ setter, getter ๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ๋งŒ์œผ๋กœ ๋Œ€์‘ํ•  ์ˆ˜ ์žˆ๋‹ค .
class MyObject{
public int mId = -1;
}
MyObject myObj = new MyObject();
myObj.mId = 2; // ๋นŒ๋“œ์—๋Ÿฌ ์—†์ด ์ปดํŒŒ์ผ ๋œ
ํ›„ ์—„์ฒญ๋‚œ side effect ๋ฅผ ๋งˆ์ฃผํ•˜๊ฒŒ ๋จ .
class MyObject{
private int mId = -1;
public int getId(){
return mId;
}
public void setId(int id){
mId = id;
}
}
MyObject myObj = new MyObject();
myObj.mId = 2; // ๋นŒ๋“œ ์—๋Ÿฌ ๋ฐœ์ƒ
์ปฌ๋ ‰์…˜ ์บก์Аํ™”
(Encapsulate Collection)
โ€ข ์ปฌ๋ ‰์…˜ ( ๋ฐฐ์—ด , ๋ฆฌ์ŠคํŠธ , ์„ธํŠธ , ๋ฒกํ„ฐ ) ์˜ getter ๋Š” ๊ฐ์ฒด ์ž์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ด์„œ๋Š” ์•ˆ๋œ๋‹ค .
โ€ข Java ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ pass by value ์ง€๋งŒ , object ๋ฅผ pass ํ•  ๋•Œ๋Š” object ์˜ reference ๊ฐ€
value ๋กœ์จ passing ๋œ ๋‹ค๋Š” ๊ฒƒ์„ ๊ธฐ์–ตํ•˜์ž .
โ€ข Thread safe ํ•œ ์ปฌ๋ ‰์…˜ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๊ธฐ์—๋„ ๋” ์šฉ์ดํ•˜๋‹ค .
public void foo(Dog d) {
d.getName().equals("Max"); // true
d = new Dog("Fifi");
d.getName().equals("Fifi"); // true
}
Dog aDog = new Dog("Max");
foo(aDog);
aDog.getName().equals("Max"); // true
public void foo(Dog d) {
d.getName().equals("Max"); // true
d.setName("Fifi");
}
Dog aDog = new Dog("Max");
foo(aDog);
aDog.getName().equals("Fifi"); // true
๋ ˆ์ฝ”๋“œ๋ฅผ ๋ฐ์ดํ„ฐ ํด๋ž˜์Šค๋กœ ์ „ํ™˜
(Replace Record with Data Class)
โ€ข ํ”„๋กœ๊ทธ๋ž˜๋ฐ ํ™˜๊ฒฝ์—์„œ ํ”ํžˆ ์‚ฌ์šฉ๋˜๋Š” ๋ ˆ์ฝ”๋“œ ๊ตฌ์กฐ๋ฅผ ๋ค ๋ฐ์ดํ„ฐ ๊ฐœ์ฒด๋กœ
์ „ํ™˜ํ•œ๋‹ค .
โ€ข ๋ค ๋ฐ์ดํ„ฐ๋ž€ , ๋ฐ์ดํ„ฐ๊ฐ€ ๊ฑฐ์˜ ๋“ค์–ด ์žˆ์ง€ ์•Š์€ ๊ฐ์ฒด๋กœ , ๊ธฐ๋Šฅ ์ถ”๊ฐ€ ์—†์ด
๋ฐ์ดํ„ฐ์— public ์†์„ฑ์ด๋‚˜ ์ฝ๊ธฐ / ์“ฐ๊ธฐ ๋ฉ”์„œ๋“œ๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค . ํ”„๋กœ
๊ทธ๋ž˜๋จธ ์ž…์žฅ์—์„  ๊ฐ์ฒด์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ฐœ๋…์˜ ์ •ํ†ต์  ๊ฐœ๋…์— ์œ„๋ฐฐ๋œ
๋‹ค . ํŒจํ„ด / ์•ˆํ‹ฐํŒจํ„ด์˜ ์‚ฌ์šฉ์€ ์บก์Аํ™”์— ์™„์ „ํžˆ ์œ„๋ฐฐ๋œ๋‹ค .
๋ถ„๋ฅ˜ ๋ถ€ํ˜ธ๋ฅผ ํด๋ž˜์Šค๋กœ ์ „ํ™˜
(ReplaceType Code with Class)
โ€ข ์ˆซ์žํ˜• ๋ถ„๋ฅ˜๋ฒˆํ˜ธ๋ฅผ ๋ณ„๋„์˜ ํด๋ž˜์Šค๋กœ ์ „ํ™˜ํ•˜๋ฉด ์ฝ”๋“œ๊ฐ€ ์ƒ๋‹นํžˆ ์ดํ•ดํ•˜๊ธฐ
์‰ฌ์›Œ์ง„๋‹ค .
โ€ข ์ฑ…์ด ์ง‘ํ•„๋œ ์‹œ์ ์˜ java version ์—” enum type ์ด ์—†์–ด์„œ์ธ์ง€ enum
type ๊ฐ™์€ class ๋ฅผ ๋ณ„๋„๋กœ ๋งŒ๋“ค์–ด์„œ ์„ค๋ช…ํ•˜๊ณ  ์žˆ๋‹ค . ์ฐธ๊ณ ๋งŒํ•˜๊ณ  ๊ทธ๋ƒฅ
enum type ์„ ์“ฐ๋ฉด ๋ ๋“ฏ ?
public enum Blood {
O(1), A(2), B(3), AB(4);
private int value = 0;
Blood(int i) { value = i; }
public int getNumber() { return value; }
public static Blood get(int value) {
if (value == O.getNumber())
return O;
else if (value == A.getNumber())
return A;
else if (value == B.getNumber())
return B;
else if (value == AB.getNumber())
return AB;
return AB;
}
}
๋ถ„๋ฅ˜ ๋ถ€ํ˜ธ๋ฅผ ํ•˜์œ„ํด๋ž˜์Šค๋กœ ์ „ํ™˜
(ReplaceType Code with SubClasses)
โ€ข ๋ถ„๋ฅ˜ ๋ถ€ํ˜ธ๊ฐ€ ํด๋ž˜์Šค ๊ธฐ๋Šฅ์— ์˜ํ–ฅ์„ ์ค˜์„œ ํด๋ž˜์Šค๋กœ ์ „ํ™˜ ๊ธฐ๋ฒ•์„ ์‚ฌ์šฉํ• 
์ˆ˜ ์—†์„ ๊ฒฝ์šฐ ์žฌ์ •์˜๋ฅผ ํ†ตํ•ด ์กฐ๊ธˆ์”ฉ ๋‹ค๋ฅธ ๊ธฐ๋Šฅ์„ ์ฒ˜๋ฆฌํ•˜๊ฒŒ ํ•œ๋‹ค .
โ€ข ์ด์™€ ๊ฐ™์ด ์ด ๊ธฐ๋ฒ•์€ ๋‹คํ˜•์„ฑ์„ ๊ฐ€๋Šฅ์ผ€ํ•˜๋Š”
์‚ฌ์ „์ž‘์—…์œผ๋กœ ์‹œํ–‰ํ•  ๋•Œ๊ฐ€ ๋งŽ๋‹ค .
public class Employee {
private int _type;
static final int ENGINEER = 0;
static final int SALESMAN =
1;
static final int MANAGER = 2;
Employee (int type) {
_type = type;
}
}
public class Engineer extends Employee {
protected Engineer(int type) {
super(type);
}
@Override
public int get_type() {
return Engineer.ENGINEER;
}
}
public abstract class Employee {
private int _type;
static final int ENGINEER = 0;
static final int SALESMAN = 1;
static final int MANAGER = 2;
protected Employee(int type) {
_type = type;
}
public static Employee createEmployee(int type) {
// if(type == ENGINEER) return new Engineer(type);
// else return new Employee(type);
switch (type) {
case ENGINEER:
return new Engineer(type);
case SALESMAN:
return new Manager(type);
case MANAGER:
return new Manager(type);
default:
throw new IllegalArgumentException(โ€œIncorrect Type Codeโ€);
}
}
abstract int get_type();
}
๋ถ„๋ฅ˜ ๋ถ€ํ˜ธ๋ฅผ ์ƒํƒœ / ์ „๋žต ํŒจํ„ด์œผ๋กœ ์ „ํ™˜
(ReplaceType Code with State/Strategy)
โ€ข ์ด ๊ธฐ๋ฒ•์€ โ€œ๋ถ„๋ฅ˜ ๋ถ€ํ˜ธ๋ฅผ ํ•˜์œ„ํด๋ž˜์Šค๋กœ ์ „ํ™˜๏ผ‚๊ณผ ๋น„์Šทํ•˜์ง€๋งŒ , ๋ถ„๋ฅ˜ ๋ถ€ํ˜ธ
๊ฐ€ ๊ฐ์ฒด ์ˆ˜๋ช…์ฃผ๊ธฐ ๋™์•ˆ ๋ณ€ํ•  ๋•Œ๋‚˜ ๋‹ค๋ฅธ ์ด์œ ๋กœ ํ•˜์œ„ํด๋ž˜์Šค๋กœ ๋งŒ๋“ค ์ˆ˜ ์—†
์„ ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค .
class Employee {
private int _type;
static final int ENGINEER = 0;
static final int SALESMAN = 1;
static final int MANAGER = 2;
Employee (int type) {
_type = type;
}
int payAmount() {
switch (_type) {
case ENGINEER:
return _monthlySalary;
case SALESMAN:
return _monthlySalary + _commission;
case MANAGER:
return _monthlySalary + _bonus;
default:
throw new RuntimeException("Incorrect Employee");
}
}
๋ถ„๋ฅ˜ ๋ถ€ํ˜ธ๋ฅผ ์ƒํƒœ / ์ „๋žต ํŒจํ„ด์œผ๋กœ ์ „ํ™˜
(ReplaceType Code with State/Strategy)
class Engineer extends EmployeeType {
int getTypeCode () {
return Employee.ENGINEER;
}
}
class Manager extends EmployeeType {
int getTypeCode () {
return Employee.MANAGER;
}
}
class Salesman extends EmployeeType {
int getTypeCode () {
return Employee.SALESMAN;
}
}
class EmployeeType...
static EmployeeType newType(int code) {
switch (code) {
case ENGINEER:
return new Engineer();
case SALESMAN:
return new Salesman();
case MANAGER:
return new Manager();
default:
throw ..
}
}
static final int ENGINEER = 0;
static final int SALESMAN = 1;
static final int MANAGER = 2;
}
class Employee...
int getType() {
return _type.getTypeCode();
}
void setType(int arg) {
_type = EmployeeType.newType(arg);
}
int payAmount() {
switch (getType()) {
case EmployeeType.ENGINEER:
return _monthlySalary;
case EmployeeType.SALESMAN:
return _monthlySalary + _commission;
case EmployeeType.MANAGER:
return _monthlySalary + _bonus;
default:
throw new RuntimeException("Incorrect Employee");
}
}
ํ•˜์œ„ํด๋ž˜์Šค๋ฅผ ํ•„๋“œ๋กœ ์ „ํ™˜
(Replace Subclass with Fields)
โ€ข ๋‹จ์ˆœํžˆ ์ƒ์ˆ˜ ๋ฉ”์„œ๋“œ๋งŒ ์กด์žฌํ•˜๋Š” ํ•˜์œ„ํด๋ž˜์Šค๋Š” ์ƒ์œ„ํด๋ž˜์Šค์˜ ํ•„๋“œ๋กœ ์ „
ํ™˜ํ•˜๊ณ  , ํ•˜์œ„ํด๋ž˜์Šค๋Š” ์™„์ „ํžˆ ์‚ญ์ œํ•˜๋ฉด ๋œ๋‹ค .
abstract class Person {
abstract boolean isMale();
abstract char getCode();
...
}
class Male extends Person {
boolean isMale() {
return true;
}
char getCode() {
return 'M';
}
}
class Female extends Person {
boolean isMale() {
return false;
}
char getCode() {
return 'F';
}
}
abstract class Person {
private final boolean _isMale;
private final char _code;
static Person createMale(){
return new Person(true, 'M');
}
static Person createFemale(){
return new Person(false, โ€˜F');
}
...
}

Refactoring - Chapter 8.2

  • 1.
  • 2.
    ๋งˆ๋ฒ• ์ˆซ์ž๋ฅผ ๊ธฐํ˜ธ์ƒ์ˆ˜๋กœ ์ „ํ™˜ (Replace Magic Number with Symbolic Constant) โ€ข ๋งˆ๋ฒ• ์ˆซ์ž๋Š” ํŠน์ˆ˜ํ•œ ๊ฐ’์„ ๊ฐ–๋Š” ์ˆซ์ž๋ฅผ ์ผ์ปซ๋Š” ์šฉ์–ด๋กœ , ์—ฌ๋Ÿฌ ๊ณณ์—์„œ ๋…ผ๋ฆฌ์ ์œผ๋กœ ๊ฐ™์€ ์ˆซ์ž๋ฅผ ์ฐธ์กฐํ•ด์•ผ ํ•  ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์€๋ฐ , ์ˆ˜์ •ํ•ด์•ผ ํ•  ์ƒํ™ฉ์ด ์˜ค๋ฉด ๋”์ฐํ•œ ์ผ์ด ๋ฐœ์ƒํ•œ๋‹ค . โ€ข ์ฆ‰ , ์ƒ์ˆ˜๋ฅผ ํ•˜๋“œ์ฝ”๋”ฉํ•˜์ง€ ๋ง์ž . class TestA{ public boolean isOverFlow(int curCount){ if(curCount > 10){ return true; } return false; } } class TestB{ public int getMaxCount(){ return 10; } } class TestA{ public boolean isOverFlow(int curCount){ if(curCount > CommonConst.MAX_COUNT){ return true; } return false; } } class TestB{ public int getMaxCount(){ return CommonConst.MAX_COUNT; } } interface CommonConst{ public int MAX_COUNT = 10; }
  • 3.
    ํ•„๋“œ ์บก์Аํ™” (Encapsulate Field) โ€ข๋ฐ์ดํ„ฐ๋Š” ์ ˆ๋Œ€๋กœ public ์œผ๋กœ ์„ ์–ธํ•˜๋ฉด ์•ˆ๋œ๋‹ค . ๋ฐ˜๋“œ์‹œ private ํ˜•ํƒœ์—์„œ setter, getter ๋ฅผ๋งŒ๋“ค์–ด ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค . โ€ข ์–ผํ• ์ƒ๊ฐํ•˜๊ธฐ์—” , publi ์œผ๋กœ ํ•˜๋“  , setter, getter ๋ฅผ ๋งŒ๋“ค๋“  ์™ธ๋ถ€์—์„œ ๊ฐ’์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์€ ๋งคํ•œ๊ฐ€์ง€ ์•„๋‹Œ๊ฐ€ ๋ผ๊ณ  ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ์ง€๋งŒ , ์‹ค์ œ ์ฝ”๋”ฉ์„ ํ•ด๋ณด๋ฉด ๊ทธ๋ ‡์ง€ ์•Š๋‹ค ๋Š” ๊ฒƒ์„ ๋А๋‚„ ์ˆ˜ ์žˆ๋‹ค . ์˜ˆ๋ฅผ ๋“ค์–ด , ์•„๋ž˜์™€ ๊ฐ™์€ ์‚ฌ์†Œํ•œ ์‹ค์ˆ˜๋ฅผ ๋ฏธ์—ฐ์— ๋ฐฉ์ง€ํ•  ์ˆ˜๋„ ์žˆ ๊ณ  , ๋ฌด์—‡๋ณด๋‹ค ๋ณ€์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๊ฑฐ๋‚˜ ์„ธํŒ…ํ•  ๋•Œ ์ผ๊ด„ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•  ์ฝ”๋“œ๊ฐ€ ์ถ”๊ฐ€๋  ๊ฒฝ์šฐ ํ•ด ๋‹น ๋ณ€์ˆ˜์˜ setter, getter ๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ๋งŒ์œผ๋กœ ๋Œ€์‘ํ•  ์ˆ˜ ์žˆ๋‹ค . class MyObject{ public int mId = -1; } MyObject myObj = new MyObject(); myObj.mId = 2; // ๋นŒ๋“œ์—๋Ÿฌ ์—†์ด ์ปดํŒŒ์ผ ๋œ ํ›„ ์—„์ฒญ๋‚œ side effect ๋ฅผ ๋งˆ์ฃผํ•˜๊ฒŒ ๋จ . class MyObject{ private int mId = -1; public int getId(){ return mId; } public void setId(int id){ mId = id; } } MyObject myObj = new MyObject(); myObj.mId = 2; // ๋นŒ๋“œ ์—๋Ÿฌ ๋ฐœ์ƒ
  • 4.
    ์ปฌ๋ ‰์…˜ ์บก์Аํ™” (Encapsulate Collection) โ€ข์ปฌ๋ ‰์…˜ ( ๋ฐฐ์—ด , ๋ฆฌ์ŠคํŠธ , ์„ธํŠธ , ๋ฒกํ„ฐ ) ์˜ getter ๋Š” ๊ฐ์ฒด ์ž์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ด์„œ๋Š” ์•ˆ๋œ๋‹ค . โ€ข Java ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ pass by value ์ง€๋งŒ , object ๋ฅผ pass ํ•  ๋•Œ๋Š” object ์˜ reference ๊ฐ€ value ๋กœ์จ passing ๋œ ๋‹ค๋Š” ๊ฒƒ์„ ๊ธฐ์–ตํ•˜์ž . โ€ข Thread safe ํ•œ ์ปฌ๋ ‰์…˜ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๊ธฐ์—๋„ ๋” ์šฉ์ดํ•˜๋‹ค . public void foo(Dog d) { d.getName().equals("Max"); // true d = new Dog("Fifi"); d.getName().equals("Fifi"); // true } Dog aDog = new Dog("Max"); foo(aDog); aDog.getName().equals("Max"); // true public void foo(Dog d) { d.getName().equals("Max"); // true d.setName("Fifi"); } Dog aDog = new Dog("Max"); foo(aDog); aDog.getName().equals("Fifi"); // true
  • 5.
    ๋ ˆ์ฝ”๋“œ๋ฅผ ๋ฐ์ดํ„ฐ ํด๋ž˜์Šค๋กœ์ „ํ™˜ (Replace Record with Data Class) โ€ข ํ”„๋กœ๊ทธ๋ž˜๋ฐ ํ™˜๊ฒฝ์—์„œ ํ”ํžˆ ์‚ฌ์šฉ๋˜๋Š” ๋ ˆ์ฝ”๋“œ ๊ตฌ์กฐ๋ฅผ ๋ค ๋ฐ์ดํ„ฐ ๊ฐœ์ฒด๋กœ ์ „ํ™˜ํ•œ๋‹ค . โ€ข ๋ค ๋ฐ์ดํ„ฐ๋ž€ , ๋ฐ์ดํ„ฐ๊ฐ€ ๊ฑฐ์˜ ๋“ค์–ด ์žˆ์ง€ ์•Š์€ ๊ฐ์ฒด๋กœ , ๊ธฐ๋Šฅ ์ถ”๊ฐ€ ์—†์ด ๋ฐ์ดํ„ฐ์— public ์†์„ฑ์ด๋‚˜ ์ฝ๊ธฐ / ์“ฐ๊ธฐ ๋ฉ”์„œ๋“œ๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค . ํ”„๋กœ ๊ทธ๋ž˜๋จธ ์ž…์žฅ์—์„  ๊ฐ์ฒด์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ฐœ๋…์˜ ์ •ํ†ต์  ๊ฐœ๋…์— ์œ„๋ฐฐ๋œ ๋‹ค . ํŒจํ„ด / ์•ˆํ‹ฐํŒจํ„ด์˜ ์‚ฌ์šฉ์€ ์บก์Аํ™”์— ์™„์ „ํžˆ ์œ„๋ฐฐ๋œ๋‹ค .
  • 6.
    ๋ถ„๋ฅ˜ ๋ถ€ํ˜ธ๋ฅผ ํด๋ž˜์Šค๋กœ์ „ํ™˜ (ReplaceType Code with Class) โ€ข ์ˆซ์žํ˜• ๋ถ„๋ฅ˜๋ฒˆํ˜ธ๋ฅผ ๋ณ„๋„์˜ ํด๋ž˜์Šค๋กœ ์ „ํ™˜ํ•˜๋ฉด ์ฝ”๋“œ๊ฐ€ ์ƒ๋‹นํžˆ ์ดํ•ดํ•˜๊ธฐ ์‰ฌ์›Œ์ง„๋‹ค . โ€ข ์ฑ…์ด ์ง‘ํ•„๋œ ์‹œ์ ์˜ java version ์—” enum type ์ด ์—†์–ด์„œ์ธ์ง€ enum type ๊ฐ™์€ class ๋ฅผ ๋ณ„๋„๋กœ ๋งŒ๋“ค์–ด์„œ ์„ค๋ช…ํ•˜๊ณ  ์žˆ๋‹ค . ์ฐธ๊ณ ๋งŒํ•˜๊ณ  ๊ทธ๋ƒฅ enum type ์„ ์“ฐ๋ฉด ๋ ๋“ฏ ? public enum Blood { O(1), A(2), B(3), AB(4); private int value = 0; Blood(int i) { value = i; } public int getNumber() { return value; } public static Blood get(int value) { if (value == O.getNumber()) return O; else if (value == A.getNumber()) return A; else if (value == B.getNumber()) return B; else if (value == AB.getNumber()) return AB; return AB; } }
  • 7.
    ๋ถ„๋ฅ˜ ๋ถ€ํ˜ธ๋ฅผ ํ•˜์œ„ํด๋ž˜์Šค๋กœ์ „ํ™˜ (ReplaceType Code with SubClasses) โ€ข ๋ถ„๋ฅ˜ ๋ถ€ํ˜ธ๊ฐ€ ํด๋ž˜์Šค ๊ธฐ๋Šฅ์— ์˜ํ–ฅ์„ ์ค˜์„œ ํด๋ž˜์Šค๋กœ ์ „ํ™˜ ๊ธฐ๋ฒ•์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์„ ๊ฒฝ์šฐ ์žฌ์ •์˜๋ฅผ ํ†ตํ•ด ์กฐ๊ธˆ์”ฉ ๋‹ค๋ฅธ ๊ธฐ๋Šฅ์„ ์ฒ˜๋ฆฌํ•˜๊ฒŒ ํ•œ๋‹ค . โ€ข ์ด์™€ ๊ฐ™์ด ์ด ๊ธฐ๋ฒ•์€ ๋‹คํ˜•์„ฑ์„ ๊ฐ€๋Šฅ์ผ€ํ•˜๋Š” ์‚ฌ์ „์ž‘์—…์œผ๋กœ ์‹œํ–‰ํ•  ๋•Œ๊ฐ€ ๋งŽ๋‹ค . public class Employee { private int _type; static final int ENGINEER = 0; static final int SALESMAN = 1; static final int MANAGER = 2; Employee (int type) { _type = type; } } public class Engineer extends Employee { protected Engineer(int type) { super(type); } @Override public int get_type() { return Engineer.ENGINEER; } } public abstract class Employee { private int _type; static final int ENGINEER = 0; static final int SALESMAN = 1; static final int MANAGER = 2; protected Employee(int type) { _type = type; } public static Employee createEmployee(int type) { // if(type == ENGINEER) return new Engineer(type); // else return new Employee(type); switch (type) { case ENGINEER: return new Engineer(type); case SALESMAN: return new Manager(type); case MANAGER: return new Manager(type); default: throw new IllegalArgumentException(โ€œIncorrect Type Codeโ€); } } abstract int get_type(); }
  • 8.
    ๋ถ„๋ฅ˜ ๋ถ€ํ˜ธ๋ฅผ ์ƒํƒœ/ ์ „๋žต ํŒจํ„ด์œผ๋กœ ์ „ํ™˜ (ReplaceType Code with State/Strategy) โ€ข ์ด ๊ธฐ๋ฒ•์€ โ€œ๋ถ„๋ฅ˜ ๋ถ€ํ˜ธ๋ฅผ ํ•˜์œ„ํด๋ž˜์Šค๋กœ ์ „ํ™˜๏ผ‚๊ณผ ๋น„์Šทํ•˜์ง€๋งŒ , ๋ถ„๋ฅ˜ ๋ถ€ํ˜ธ ๊ฐ€ ๊ฐ์ฒด ์ˆ˜๋ช…์ฃผ๊ธฐ ๋™์•ˆ ๋ณ€ํ•  ๋•Œ๋‚˜ ๋‹ค๋ฅธ ์ด์œ ๋กœ ํ•˜์œ„ํด๋ž˜์Šค๋กœ ๋งŒ๋“ค ์ˆ˜ ์—† ์„ ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค . class Employee { private int _type; static final int ENGINEER = 0; static final int SALESMAN = 1; static final int MANAGER = 2; Employee (int type) { _type = type; } int payAmount() { switch (_type) { case ENGINEER: return _monthlySalary; case SALESMAN: return _monthlySalary + _commission; case MANAGER: return _monthlySalary + _bonus; default: throw new RuntimeException("Incorrect Employee"); } }
  • 9.
    ๋ถ„๋ฅ˜ ๋ถ€ํ˜ธ๋ฅผ ์ƒํƒœ/ ์ „๋žต ํŒจํ„ด์œผ๋กœ ์ „ํ™˜ (ReplaceType Code with State/Strategy) class Engineer extends EmployeeType { int getTypeCode () { return Employee.ENGINEER; } } class Manager extends EmployeeType { int getTypeCode () { return Employee.MANAGER; } } class Salesman extends EmployeeType { int getTypeCode () { return Employee.SALESMAN; } } class EmployeeType... static EmployeeType newType(int code) { switch (code) { case ENGINEER: return new Engineer(); case SALESMAN: return new Salesman(); case MANAGER: return new Manager(); default: throw .. } } static final int ENGINEER = 0; static final int SALESMAN = 1; static final int MANAGER = 2; } class Employee... int getType() { return _type.getTypeCode(); } void setType(int arg) { _type = EmployeeType.newType(arg); } int payAmount() { switch (getType()) { case EmployeeType.ENGINEER: return _monthlySalary; case EmployeeType.SALESMAN: return _monthlySalary + _commission; case EmployeeType.MANAGER: return _monthlySalary + _bonus; default: throw new RuntimeException("Incorrect Employee"); } }
  • 10.
    ํ•˜์œ„ํด๋ž˜์Šค๋ฅผ ํ•„๋“œ๋กœ ์ „ํ™˜ (ReplaceSubclass with Fields) โ€ข ๋‹จ์ˆœํžˆ ์ƒ์ˆ˜ ๋ฉ”์„œ๋“œ๋งŒ ์กด์žฌํ•˜๋Š” ํ•˜์œ„ํด๋ž˜์Šค๋Š” ์ƒ์œ„ํด๋ž˜์Šค์˜ ํ•„๋“œ๋กœ ์ „ ํ™˜ํ•˜๊ณ  , ํ•˜์œ„ํด๋ž˜์Šค๋Š” ์™„์ „ํžˆ ์‚ญ์ œํ•˜๋ฉด ๋œ๋‹ค . abstract class Person { abstract boolean isMale(); abstract char getCode(); ... } class Male extends Person { boolean isMale() { return true; } char getCode() { return 'M'; } } class Female extends Person { boolean isMale() { return false; } char getCode() { return 'F'; } } abstract class Person { private final boolean _isMale; private final char _code; static Person createMale(){ return new Person(true, 'M'); } static Person createFemale(){ return new Person(false, โ€˜F'); } ... }