1. μμ±μ λμ μ μ ν©ν 리 λ©μλ !
πΉ μ μ ν©ν 리 λ©μλ (static factory method)
π ν΄λΉ ν΄λμ€μ μΈμ€ν΄μ€ λ°ν
μ΄λ―Έ μΊμλ κ°μ²΄ λ°ννμ¬ κ°μ²΄ μμ± μ€μ
π μ₯μ
- μ΄λ¦μ κ°μ§ μ μμ΄μ λ°νλ κ°μ²΄μ νΉμ±μ μ λλ‘ μ€λͺ
κ°λ₯
ex) BigInteger(int, int, Random) vs BigInteger.probablePrime
π λ μ€ 'κ°μ΄ μμμΈ BigIntegerλ₯Ό λ°ννλ€'λ μλ―Έλ₯Ό λ μ μ€λͺ ν μ μλ κ²μ λ°λ‘ νμ κ°λ₯ - ν ν΄λμ€μ μκ·Έλμ²κ° κ°μ μμ±μκ° μ¬λ¬ κ° νμν μ μ μ ν©ν 리 λ©μλλ₯Ό νμ©νλ κ²μ΄ λμ± μ μ©
public class Account {
private String owner;
private double balance;
// private μμ±μ
private Account(String owner, double balance) {
this.owner = owner;
this.balance = balance;
}
// μΌλ° κ³μ’ μμ±μ© ν©ν 리 λ©μλ
public static Account createNormalAccount(String owner, double initialDeposit) {
return new Account(owner, initialDeposit);
}
// VIP κ³μ’ μμ±μ© ν©ν 리 λ©μλ
public static Account createVIPAccount(String owner, double initialDeposit) {
return new Account(owner, initialDeposit + 1000); // VIP 보λμ€ μΆκ°
}
@Override
public String toString() {
return "Account{owner='" + owner + "', balance=" + balance + "}";
}
public static void main(String[] args) {
// μ μ ν©ν 리 λ©μλλ₯Ό ν΅ν κ³μ’ μμ±
Account normalAccount = Account.createNormalAccount("John Doe", 1000);
Account vipAccount = Account.createVIPAccount("Jane Doe", 2000);
System.out.println(normalAccount);
System.out.println(vipAccount);
}
}
- νΈμΆλ λλ§λ€ μΈμ€ν΄μ€ μλ‘ μμ± X π λΆνμν λ©λͺ¨λ¦¬ λλΉ μ€μ΄κ³ μ±λ₯ μ΅μ ν κ°λ₯
- λ°ννμ
μ νμ νμ
κ°μ²΄λ₯Ό λ°νν μ μμ΄ λ°νν κ°μ²΄μ ν΄λμ€λ₯Ό μμ λ‘κ² μ ν κ°λ₯
- μ λ ₯ 맀κ°λ³μμ λ°λΌ λ§€λ² λ€λ₯Έ ν΄λμ€μ κ°μ²΄ λ°ν κ°λ₯
public class Main {
public static void main(String[] args) {
// μ μ ν©ν 리 λ©μλλ₯Ό ν΅ν΄ Animal νμ
λ°ν
Animal animal1 = AnimalFactory.createAnimal("dog");
animal1.speak(); // μΆλ ₯: Woof!
Animal animal2 = AnimalFactory.createAnimal("cat");
animal2.speak(); // μΆλ ₯: Meow!
}
}
π λ¨μ
- μ μ ν©ν 리 λ©μλλ₯Ό νλ‘κ·Έλλ¨Έκ° μ°ΎκΈ° μ΄λ €μ π μμ±μμ²λΌ API μ€λͺ μ λͺ νν λλ¬λμ§ X
- μ νμ 맀κ°λ³μκ° λ§μ λ μ μ ν λ°μ μ΄λ €μ (μμ±μλ λ§μ°¬κ°μ§)
β³οΈ νν μ¬μ©νλ λͺ λͺ λ°©μ
- from : 맀κ°λ³μλ₯Ό νλ λ°μμ ν΄λΉ νμ μ μΈμ€ν΄μ€ λ°ν π νλ³ν λ©μλ
- of : μ¬λ¬ 맀κ°λ³μλ₯Ό λ°μ μ ν©ν νμ μ μΈμ€ν΄μ€ λ°ν π μ§κ³ λ©μλ
- valueOf : fromκ³Ό ofμ λ μμΈν λ²μ
- instance λλ getInstance : 맀κ°λ³μλ‘ λͺ μν μΈμ€ν΄μ€ λ°ννμ§λ§ κ°μ μΈμ€ν΄μ€μ 보μ₯ X
- create λλ newInstance : λ§€λ² μλ‘μ΄ μΈμ€ν΄μ€λ₯Ό μμ±ν΄ λ°νν¨ λ³΄μ₯
- getType : getInstanceμ κ°μΌλ μμ±ν ν΄λμ€κ° μλ λ€λ₯Έ ν΄λμ€μ ν©ν 리 λ©μλλ₯Ό μ μν λ μ¬μ©
- newType : newInstanceμ κ°μΌλ, μμ±ν ν΄λμ€κ° μλ λ€λ₯Έ ν΄λμ€μ ν©ν 리 λ©μλλ₯Ό μ μν λ μ¬μ©
π FileStore fs = Files.getFileStore(path) - type : getTypeκ³Ό newTypeμ κ°κ²°ν λ²μ
π List<Complaint> litany = Collections.list(legacyLitany)
β‘οΈ "Type" μ ν©ν 리 λ©μλκ° λ°νν κ°μ²΄μ νμ
2. μμ±μμ 맀κ°λ³μκ° λ§μΌλ©΄ Builderλ‘ !
- μ μΈ΅μ μμ±μ ν¨ν΄
: μ ν 맀κ°λ³μλ₯Ό μ λΆ λ€ λ°λ μμ±μκΉμ§ λλ €κ°λ λ°©μ
β νμ₯νκΈ° μ΄λ €μ
맀κ°λ³μ κ°μκ° λ§μμ§λ©΄ ν΄λΌμ΄μΈνΈ μ½λλ₯Ό μμ±νκ±°λ μ½κΈ° μ΄λ €μ
ν΄λΌμ΄μΈνΈκ° μ€μλ‘ λ§€κ°λ³μμ μμλ₯Ό λ°κΏ 건λ€μ€λ μ»΄νμΌλ¬λ μμμ±μ§ λͺ»ν¨ - Java Beans
: 맀κ°λ³μκ° μλ μμ±μλ‘ κ°μ²΄λ₯Ό λ§λ ν, setter λ©μλλ₯Ό νΈμΆν΄ μνλ 맀κ°λ³μμ κ° μ€μ
β μΌκ΄μ±μ΄ κΉ¨μ§κ³ λΆλ³μΌλ‘ λ§λ€ μ μμ
κ°μ²΄ νλλ₯Ό λ§λλ €λ©΄ λ©μλλ₯Ό μ¬λ¬ κ° νΈμΆν΄μΌν¨
κ°μ²΄κ° μμ ν μμ±λκΈ° μ κΉμ§λ μΌκ΄μ± 무λμ§
μ¬κΈ°μ μΌκ΄μ±μ΄ 무λμ§λ€λ κ²μ...?
π μ€κ°μ μΌλΆ κ°λ§ μ€μ λ μνμμ κ°μ²΄κ° μ‘΄μ¬ν΄ λΆμμ ν μνμ
π λ§μ½ κ°μ²΄κ° μ¬λ¬ νλλ₯Ό κ°μ ΈμΌ νλλ°, setterλ₯Ό ν΅ν΄ νλκ° μ°¨λ‘λ‘ μ€μ λλ λμ λ€λ₯Έ μ½λμμ μ΄ κ°μ²΄μ μ κ·Όν μ μλ€λ©΄, κ°μ²΄κ° μμ§ μμ ν μ΄κΈ°νλμ§ μμ μνμμ μ¬μ©λλ―λ‘ μ€λ₯ λ°μ
π setter λ©μλλ‘ μΈν΄ κ°μ²΄κ° μμ±λ μ΄νμλ κ·Έ μνκ° λ³κ²½λ μ μμ
π μμ κ°μ λ°©λ²μ΄ μμΌλ λΉλ ν¨ν΄μ μ¬μ©νλ©΄ ν¨μ¨μ μ΄λ€ !
β³οΈ Builder ν¨ν΄
- νμν κ°μ²΄λ₯Ό μ§μ λ§λλ λμ , νμ 맀κ°λ³μλ§μΌλ‘ μμ±μ νΉμ μ μ ν©ν 리λ₯Ό νΈμΆν΄ λΉλ κ°μ²΄λ₯Ό μ»μ
κ·Έ ν λΉλ κ°μ²΄κ° μ 곡νλ μΌμ’ μ setter λ©μλλ‘ μνλ μ ν 맀κ°λ³μ μ€μ νκ³ , 맀κ°λ³μκ° μλ build λ©μλλ₯Ό νΈμΆν΄ νμν κ°μ²΄λ₯Ό μ»μ - builderλ μμ±ν ν΄λμ€ μμ μ μ λ©€λ² ν΄λμ€λ‘ λ§λ€μ΄ λ
class Person {
// νλλ€ (λͺ¨λ νλλ λΆλ³μΌλ‘ μ€μ )
private final String name;
private final int age;
private final String address;
// Personμ private μμ±μ (Builderκ° νΈμΆ)
private Person(Builder builder) {
this.name = builder.name;
this.age = builder.age;
this.address = builder.address;
}
// Builder λ΄λΆ ν΄λμ€
public static class Builder {
private String name; // νλλ€ (κΈ°λ³Έκ° μ€μ κ°λ₯)
private int age;
private String address;
// name νλλ₯Ό μ€μ νλ λ©μλ (Builder κ°μ²΄ λ°ν)
public Builder setName(String name) {
this.name = name;
return this; // λ©μλ 체μ΄λμ μν΄ this λ°ν
}
// age νλλ₯Ό μ€μ νλ λ©μλ (Builder κ°μ²΄ λ°ν)
public Builder setAge(int age) {
this.age = age;
return this;
}
// address νλλ₯Ό μ€μ νλ λ©μλ (Builder κ°μ²΄ λ°ν)
public Builder setAddress(String address) {
this.address = address;
return this;
}
// build() λ©μλ: μμ±λ Person κ°μ²΄λ₯Ό λ°ν
public Person build() {
return new Person(this); // μμ ν Person κ°μ²΄ μμ±
}
}
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + ", address='" + address + "'}";
}
}
public class Main {
public static void main(String[] args) {
// λΉλ ν¨ν΄μ ν΅ν΄ Person κ°μ²΄ μμ±
Person person = new Person.Builder()
.setName("John")
.setAge(30)
.setAddress("123 Main St")
.build(); // μμ±λ Person κ°μ²΄ μμ±
// κ²°κ³Ό μΆλ ₯
System.out.println(person);
// Person{name='John', age=30, address='123 Main St'}
}
}
import lombok.Builder;
import lombok.ToString;
@Builder // 둬볡μ @Builder μ΄λ
Έν
μ΄μ
μ μ©
@ToString // κ°μ²΄ λ΄μ©μ μΆλ ₯νκΈ° μν΄ @ToString μ΄λ
Έν
μ΄μ
μ μ©
class Person {
private String name;
private int age;
private String address;
}
public class Main {
public static void main(String[] args) {
// @Builder μ΄λ
Έν
μ΄μ
μΌλ‘ μμ±λ λΉλ ν¨ν΄ μ¬μ©
Person person = Person.builder()
.name("John")
.age(30)
.address("123 Main St")
.build();
// κ²°κ³Ό μΆλ ₯
System.out.println(person); // Person(name=John, age=30, address=123 Main St)
}
}
β¨ Builder ν¨ν΄μ κ³μΈ΅μ μΌλ‘ μ€κ³λ ν΄λμ€μ ν¨κ» μ°κΈ° μ’μ !
- μΆμ λΉλ ν΄λμ€λ₯Ό ν΅ν΄ λ€μν μ’ λ₯μ νΌμ κ°μ²΄λ₯Ό μ μ°νκ² μμ± κ°λ₯
public abstract class Pizza{
public enum Topping {HAM, SAUSAGE, MUSHROOM, ONION, PEPPER}
final Set<Topping> toppings;
// μΆμ λΉλ ν΄λμ€
// λΉλ ν¨ν΄μ λ©μλ 체μ΄λμ κ°λ₯νκ² ν¨
abstract static class Builder<T extends Builder<T>> {
EnumSet<Topping> toppings = EnumSet.noneOf(Topping.class); // μ΄κΈ°μλ μ무 ν νλ μλ μν
public T addTopping(Topping topping){
toppings.add(Objects.requireNonNull(topping));
return self(); // μκΈ° μμ (νμ ν΄λμ€μ λΉλ)μ λ°ννμ¬ λ©μλ 체μ΄λμ΄ κ°λ₯νλλ‘ ν¨
}
abstract Pizza build(); // νμ ν΄λμ€μμ μ΄ λ©μλλ₯Ό ꡬ체μ μΌλ‘ ꡬνν΄μΌν¨
// νμ ν΄λμ€λ μ΄ λ©μλλ₯Ό overridingνμ¬ "this"(μκΈ° μμ )λ₯Ό λ°ννλλ‘ ν΄μΌν¨
// λ©μλ 체μ΄λμ κ°λ₯νκ² νκ³ , λΉλ ν΄λμ€μ νμ ν΄λμ€μμ μμ μ λ°ννλλ‘ κ°μ
protected abstract T self();
}
Pizza(Builder<?> builder) {
toppings = builder.toppings.clone();
}
}
public class VeggiePizza extends Pizza {
public enum Size {SMALL, MEDIUM, LARGE}
private final Size size;
public static class Builder extends Pizza.Builder<Builder> {
private final Size size;
public Builder(Size size){
this.size = Objects.requireNonNull(size);
}
@Override
public VeggiePizza build() {
return new VeggiePizza(this);
}
@Override
protected Builder self() {
return this;
}
}
private VeggiePizza(Builder builder) {
super(builder); // μμ ν΄λμ€ Pizzaμ μμ±μ νΈμΆ
size = builder.size;
}
}
VeggiePizza pizza = new VeggiePizza.Builder(SMALL)
.addTopping(SAUSAGE)
.addTopping(PEPPER).build();
π μ₯μ
- κ°λ μ± ν₯μ
- λΆλ³ κ°μ²΄ μμ±
- νλ μ νμ μ€μ
- νμ₯μ± λ° μ μ°μ±
π λ¨μ
- κ°μ²΄λ₯Ό λ§λ€λ €λ©΄ κ·Έμ μμ λΉλλΆν° λ§λ€μ΄μΌ ν¨ (맀κ°λ³μκ° 4κ° μ΄μμ λμ΄μΌ κ°μ΄μΉλ₯Ό ν¨)
π Lombokμμ μ 곡νλ @Builder μ΄λ Έν μ΄μ μΌλ‘ λΉλ ν¨ν΄ μ½κ² ꡬνν΄ ν΄κ²° !
3. private μμ±μλ μ΄κ±° νμ μΌλ‘ singletonμμ 보μ¦
Singletonμ΄λ ?
π μΈμ€ν΄μ€λ₯Ό μ€μ§ νλλ§ μμ±ν μ μλ ν΄λμ€
β³οΈ Singletonμ λ§λλ λ°©μ
- public static final νλ λ°©μ
π ν΄λΉ ν΄λμ€κ° μ±κΈν΄μμ΄ APIμ λͺ λ°±ν λλ¬λκ³ κ°κ²°ν¨
public class Singleton {
// 1. μ±κΈν΄ μΈμ€ν΄μ€λ₯Ό static finalλ‘ μ μΈνμ¬ ν΄λμ€ λ‘λ μμ μ μ΄κΈ°ν
private static final Singleton INSTANCE = new Singleton();
// 2. private μμ±μλ‘ μΈλΆμμ μΈμ€ν΄μ€νν μ μλλ‘ ν¨
private Singleton() {
// private constructor to prevent instantiation
}
// 3. μ μ ν©ν 리 λ©μλλ₯Ό ν΅ν΄ μΈμ€ν΄μ€ μ 곡
public static Singleton getInstance() {
return INSTANCE;
}
// μΈμ€ν΄μ€κ° κ°μ§λ λ©μλ
public void doSomething() {
System.out.println("Singleton instance method.");
}
}
π private μμ±μκ° public static final νλλ₯Ό μ΄κΈ°νν λ λ± ν λ²λ§ μ΄κΈ°νλ¨
public class SingletonDemo {
public static void main(String[] args) {
// μ±κΈν΄ μΈμ€ν΄μ€λ₯Ό κ°μ Έμ΄
Singleton singleton = Singleton.getInstance();
// μ±κΈν΄ λ©μλλ₯Ό νΈμΆ
singleton.doSomething();
// λ κ°μ Singleton μΈμ€ν΄μ€κ° λμΌν¨μ νμΈ
Singleton anotherSingleton = Singleton.getInstance();
System.out.println(singleton == anotherSingleton); // true
}
}
- μ μ ν©ν 리 λ°©μ
π Singleton.getInstanceλ νμ κ°μ κ°μ²΄μ μ°Έμ‘°λ₯Ό λ°ν - μ΄κ±° νμ
λ°©μ
π enum νμ©νμ¬ κ°μ₯ μμ νκ³ κ°κ²°ν λ°©μ
public enum Singleton {
// μ μΌν μ±κΈν΄ μΈμ€ν΄μ€
INSTANCE;
// μΈμ€ν΄μ€κ° κ°μ§λ λ©μλ
public void doSomething() {
System.out.println("Singleton instance method.");
}
}
β enum νμ μ public static final μΈμ€ν΄μ€ νλλ₯Ό κΈ°λ³Έμ μΌλ‘ μμ±
'Java > π Effective Java' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
[π Effective Java] ν΄λμ€μ μΈν°νμ΄μ€ δΈ (2) | 2024.10.05 |
---|---|
[π Effective Java] ν΄λμ€μ μΈν°νμ΄μ€ δΈ (1) | 2024.09.25 |
[π Effective Java] λͺ¨λ κ°μ²΄μ κ³΅ν΅ λ©μλ δΈ (0) | 2024.09.22 |
[Effective Java] λͺ¨λ κ°μ²΄μ κ³΅ν΅ λ©μλ δΈ (0) | 2024.09.21 |
[π Effective Java] κ°μ²΄ μμ±κ³Ό νκ΄΄ δΈ (0) | 2024.09.20 |