π Today I Learned 22νμ°¨ - Dart Factory μμ±μ π
μλ
νμΈμ! μ€λμ Flutter κ°λ°μλ€μ΄ λ°μ΄ν° λͺ¨λΈμ λ€λ£¨κ±°λ λμμΈ ν¨ν΄μ ꡬνν λ νμμ μΌλ‘ μ¬μ©νλ Dart μΈμ΄μ νΉλ³ν μμ±μ ν€μλ, factoryμ λν΄ μ λ¦¬ν΄ λ³΄κ² μ΅λλ€.
μΌλ°μ μΈ μμ±μμ factory μμ±μλ κ²λ³΄κΈ°μ λΉμ·νμ§λ§, λ΄λΆμ μΌλ‘λ κ°μ²΄λ₯Ό μμ±νλ λ°©μκ³Ό μν μ ν° μ°¨μ΄κ° μμ΅λλ€.
π― νμ΅ λͺ©ν
- Factory μμ±μμ κ°λ κ³Ό μΌλ° μμ±μμμ μ°¨μ΄μ μ΄ν΄νκΈ°
- Factory μμ±μλ₯Ό μ¬μ©νλ 3κ°μ§ ν΅μ¬ μ΄μ νμ΅νκΈ°
- μ±κΈν€ ν¨ν΄, JSON νμ±, μλΈν΄λμ€ λ°ν λ± μ€μ νμ© μ¬λ‘ νμ νκΈ°
- Factory μμ±μλ₯Ό νμ©ν μ€μ μ½λ μμ± μ΅νκΈ°
π μ£Όμ λ΄μ©
π 1. factoryλ 무μμΈκ°?
factory μμ±μλ μλ‘μ΄ μΈμ€ν΄μ€λ₯Ό μμ±νλ κ³Όμ μ μ§μ μ μ΄ν μ μλ μμ±μμ
λλ€. μ΄λ μμ±μμ²λΌ 보μ΄μ§λ§, μ€μ λ‘λ ν΄λΉ ν΄λμ€ μΈμ€ν΄μ€λ₯Ό λ°ννλ μ μ λ©μλ(Static Method)μ μ μ¬νκ² μλν©λλ€.
π‘ ν΅μ¬ ν¬μΈνΈ: μΌλ° μμ±μμ λ¬λ¦¬,
factoryμμ±μλ νΈμΆλ λ λ°λμ μ μΈμ€ν΄μ€λ₯Ό μμ±ν μλ¬΄κ° μλ€λ μ μ λλ€.
β 2. factoryλ₯Ό μ¬μ©νλ κ²°μ μ μΈ μ΄μ 3κ°μ§
factory ν€μλκ° μλ€λ©΄ ν΄κ²°νκΈ° μ΄λ ΅κ±°λ λΉν¨μ¨μ μΈ μν©λ€μ΄ μμ΅λλ€.
β μΈμ€ν΄μ€ μΊμ± λ° μ±κΈν€ ꡬν (κ°μ²΄ μ¬νμ©) β»οΈ
λ©λͺ¨λ¦¬ ν¨μ¨μ΄ μ€μν λ, λμΌν κ°μ²΄λ₯Ό λ§€λ² μλ‘ λ§λλ λμ μ΄λ―Έ μ‘΄μ¬νλ κ°μ²΄λ₯Ό μ¬μ¬μ©ν μ μμ΅λλ€.
- μΌλ° μμ±μ: νΈμΆλ λλ§λ€ 무쑰건 μ κ°μ²΄ μμ±.
factoryμμ±μ: λ΄λΆ λ‘μ§μ ν΅ν΄ μ΄λ―Έ μμ±λ μΈμ€ν΄μ€(μ: μ±κΈν€ μΈμ€ν΄μ€)κ° μλμ§ νμΈνκ³ , μλ€λ©΄ μλ‘ λ§λ€μ§ μκ³ κΈ°μ‘΄ μΈμ€ν΄μ€λ₯Ό λ°νν©λλ€.
β‘ μΈλΆ λ°μ΄ν°(JSON) μ²λ¦¬ λ° λ³΅μ‘ν μ΄κΈ°ν λ‘μ§ βοΈ
μΈλΆ λ°μ΄ν°(νΉν JSON Map)λ₯Ό ν΄λμ€ κ°μ²΄λ‘ λ³ννλ κ³Όμ μ λ°μ΄ν° κ²μ¦, νμ
λ³ν(int -> double), κΈ°λ³Έκ° ν λΉ λ± λ³΅μ‘ν λ‘μ§μ μꡬν©λλ€.
- μΌλ° μμ±μ: 볡μ‘ν λ‘μ§μ μμ±μμμ μ²λ¦¬νκΈ° μ΄λ ΅κ³ ,
returnλ¬Έμ μ¬μ©ν μ μμ΄ μ μ°μ±μ΄ λ¨μ΄μ§λλ€. factoryμμ±μ: ν¨μ λ³Έλ¬Έ λ΄μif/elseμ κ°μ λͺ¨λ μ μ΄ νλ¦ λ° λ‘μ§μ ꡬνν μ μμ΅λλ€. μ΄λ₯Ό ν΅ν΄ λ°μ΄ν°κ° λλ½λκ±°λ μλͺ»λ νμ μΌλ‘ λ€μ΄μμ λ μμ νκ² μ²λ¦¬ ν λͺ μμ μΌλ‘returnν μ μμ΅λλ€.
π‘ μ€μ νμ© μ¬λ‘:
Product.fromJsonκ³Ό κ°μ ν¨ν΄μμjson['key'] ?? 'κΈ°λ³Έκ°'λλ νμ μΊμ€ν μ ν΅ν΄ μμ ν κ°μ²΄ μμ±μ΄ κ°λ₯ν©λλ€.
β’ μ‘°κ±΄λΆ μλΈν΄λμ€ μΈμ€ν΄μ€ λ°ν (μΆμν) π§±
ν©ν 리 μμ±μλ νΈμΆλ ν΄λμ€ μμ²΄κ° μλ, ν΄λΉ ν΄λμ€λ₯Ό μμλ°μ λ€λ₯Έ ꡬ체μ μΈ μλΈν΄λμ€μ μΈμ€ν΄μ€λ₯Ό λ°ννλλ‘ ν μ μμ΅λλ€.
- μμ: μμ μΆμ ν΄λμ€μ
factoryμμ±μλ₯Ό νΈμΆνμ λ, μ λ ₯λ 쑰건(νλΌλ―Έν°)μ λ°λΌ μμ ν΄λμ€(Circle,Squareλ±) μ€ νλλ₯Ό μ ννμ¬ λ°νν¨μΌλ‘μ¨ μμ± λ‘μ§μ μΆμνν μ μμ΅λλ€.
π 3. μΌλ° μμ±μ vs Factory μμ±μ λΉκ΅
| κ΅¬λΆ | μΌλ° μμ±μ | factory μμ±μ |
|---|---|---|
| κ°μ²΄ μμ± | νμ μ μΈμ€ν΄μ€ μμ± | κΈ°μ‘΄ μΈμ€ν΄μ€ λ°ν κ°λ₯ |
| ν΅μ¬ μν | νλ μ΄κΈ°ν | μμ± νλ‘μΈμ€ μ μ΄ λ° κ΄λ¦¬ |
| ν€μλ | μμ | factory |
| λ©μλ λ³Έλ¬Έ | μ νμ (μ΄κΈ°ν 리μ€νΈ) | μμ λ‘μ΄ λ‘μ§ λ° return μ¬μ© κ°λ₯ |
| λ°ν νμ | νμ¬ ν΄λμ€λ§ | μλΈν΄λμ€ λ°ν κ°λ₯ |
π» μ€μ΅ λ° μμ
π§ μμ 1: μ±κΈν€ ν¨ν΄ ꡬν
// μ±κΈν€ ν¨ν΄ - μ± μ μμμ νλμ μΈμ€ν΄μ€λ§ μ¬μ©
class Logger {
static final Logger _instance = Logger._internal();
// Private μμ±μ
Logger._internal();
// Factory μμ±μ - νμ λμΌν μΈμ€ν΄μ€ λ°ν
factory Logger() {
return _instance;
}
void log(String message) {
print('[LOG] $message');
}
}
void main() {
var logger1 = Logger();
var logger2 = Logger();
// λμΌν μΈμ€ν΄μ€μΈμ§ νμΈ
print(identical(logger1, logger2)); // true
logger1.log('μ±κΈν€ ν¨ν΄ ν
μ€νΈ'); // [LOG] μ±κΈν€ ν¨ν΄ ν
μ€νΈ
}
π§ μμ 2: JSON λ°μ΄ν° νμ±
// JSON λ°μ΄ν°λ₯Ό μμ νκ² κ°μ²΄λ‘ λ³ν
class Product {
final String name;
final double price;
final String category;
Product({
required this.name,
required this.price,
required this.category,
});
// Factory μμ±μλ‘ JSON νμ± λ° κ²μ¦
factory Product.fromJson(Map<String, dynamic> json) {
// λ°μ΄ν° κ²μ¦ λ° κΈ°λ³Έκ° μ²λ¦¬
return Product(
name: json['name'] ?? 'Unknown Product',
price: (json['price'] ?? 0).toDouble(), // intλ₯Ό doubleλ‘ λ³ν
category: json['category'] ?? 'General',
);
}
}
void main() {
// μ μ λ°μ΄ν°
var product1 = Product.fromJson({
'name': 'Flutter Book',
'price': 25000,
'category': 'Books'
});
// λΆμμ ν λ°μ΄ν° - κΈ°λ³Έκ°μΌλ‘ μμ νκ² μ²λ¦¬
var product2 = Product.fromJson({'name': 'Widget'});
print('${product2.name}, ${product2.price}, ${product2.category}');
// μΆλ ₯: Widget, 0.0, General
}
π§ μμ 3: μ‘°κ±΄λΆ μλΈν΄λμ€ λ°ν
// μΆμ ν΄λμ€
abstract class Shape {
void draw();
// Factory μμ±μ - νμ
μ λ°λΌ λ€λ₯Έ μλΈν΄λμ€ λ°ν
factory Shape(String type) {
if (type == 'circle') {
return Circle();
} else if (type == 'square') {
return Square();
}
throw ArgumentError('Unknown shape type: $type');
}
}
class Circle implements Shape {
@override
void draw() {
print('β μμ 그립λλ€');
}
}
class Square implements Shape {
@override
void draw() {
print('β‘ μ¬κ°νμ 그립λλ€');
}
}
void main() {
// λμΌν μμ±μ νΈμΆμ΄μ§λ§ λ€λ₯Έ νμ
μ κ°μ²΄ λ°ν
Shape shape1 = Shape('circle');
Shape shape2 = Shape('square');
shape1.draw(); // β μμ 그립λλ€
shape2.draw(); // β‘ μ¬κ°νμ 그립λλ€
}
π μ¬ν νμ΅
π€ Factory μμ±μ νμ© ν
1. μΊμ± μ΅μ ν
- μμ£Ό μ¬μ©λλ κ°μ²΄λ
Mapμ μ μ₯νμ¬ μ¬μ¬μ© - λ©λͺ¨λ¦¬ ν¨μ¨μ± ν₯μ
2. λΆλ³ κ°μ²΄μμ μ‘°ν©
constμμ±μμ ν¨κ» μ¬μ©νμ¬ μ»΄νμΌ νμ μμ νμ©- μ±λ₯ μ΅μ ν κ°λ₯
3. λ€μ΄λ° 컨벀μ
fromJson,fromMap: λ°μ΄ν° λ³νμ©create,build: 볡μ‘ν μμ± λ‘μ§μ©
β οΈ μ£Όμμ¬ν: Factory μμ±μλ κ°λ ₯νμ§λ§ κ³Όλν μ¬μ©μ μ½λ 볡μ‘λλ₯Ό λμΌ μ μμ΅λλ€. λ¨μν κ²½μ°μλ μΌλ° μμ±μλ₯Ό μ¬μ©νλ κ²μ΄ λ λͺ νν μ μμ΅λλ€.
π λ§λ¬΄λ¦¬
β μ€λ λ°°μ΄ κ²
- Factory μμ±μμ ν΅μ¬: κ°μ²΄ μμ± κ³Όμ μ μ μ΄νλ©°, νμ μ μΈμ€ν΄μ€λ₯Ό λ§λ€ νμκ° μμ
- 3κ°μ§ μ£Όμ νμ© μ¬λ‘:
- β»οΈ μ±κΈν€ ν¨ν΄: λ©λͺ¨λ¦¬ ν¨μ¨μ μΈ μΈμ€ν΄μ€ μ¬μ¬μ©
- βοΈ JSON νμ±: μμ ν λ°μ΄ν° λ³ν λ° κ²μ¦
- π§± μλΈν΄λμ€ λ°ν: μ μ°ν κ°μ²΄ μμ± ν¨ν΄
- μΌλ° μμ±μμμ μ°¨μ΄: Factoryλ
returnλ¬Έκ³Ό 볡μ‘ν λ‘μ§ μ¬μ© κ°λ₯ - μ€μ μ½λ: Logger μ±κΈν€, Product.fromJson, Shape ν©ν 리 ν¨ν΄ ꡬν
π λ€μ κ³ν
- Freezed ν¨ν€μ§: Factory μμ±μλ₯Ό μλμΌλ‘ μμ±ν΄μ£Όλ μ½λ μμ± λΌμ΄λΈλ¬λ¦¬ νμ΅
- λμμΈ ν¨ν΄ μ¬ν: Factory Method ν¨ν΄, Abstract Factory ν¨ν΄ μ μ©
- λΆλ³ κ°μ²΄(Immutable):
constμμ±μμ Factoryμ μ‘°ν©μΌλ‘ μ±λ₯ μ΅μ ν - μ€μ νλ‘μ νΈ: API μλ΅ λ°μ΄ν° λͺ¨λΈλ§μ Factory μμ±μ μ μ©νκΈ°
λκΈλ¨κΈ°κΈ°