Item 1. Static Factory Method
์์ฑ์ ๋์ ์ ์ ํฉํฐ๋ฆฌ ๋ฉ์๋๋ฅผ ๊ณ ๋ คํ๋ผ
๋ณดํต Java๋ฅผ ์ฌ์ฉํ ๋ ํด๋์ค์ ์ธ์คํด์ค๋ฅผ ์์ฑํ ๋๋ public ์์ฑ์๋ฅผ ์ฌ์ฉํ๋ค. ํ์ง๋ง ์ด ๋ฐฉ๋ฒ ๋ง๊ณ ๋ ์๋์ ๊ฐ์ด ์ ์ ํฉํฐ๋ฆฌ ๋ฉ์๋(static factory method)๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ์ฒด๋ฅผ ์์ฑํ ์ ์๋ค.
public class Example {
private Example() {
}
public static Example of() {
return new Example();
}
}
public class Main {
public static void main(String[] args) {
Example example = Example.of();
}
}
์ ์ ํฉํฐ๋ฆฌ ๋ฉ์๋์ ์ฅ์
์ ์์ ์ฝ๋์ ๊ฐ์ด ์ ์ ํฉํฐ๋ฆฌ ๋ฉ์๋๋ฅผ ํตํ์ฌ ๊ฐ์ฒด๋ฅผ ์์ฑ์ ํ๋ฉด ๋น์ฐํ ๋จ์ ๋ค๋ ์กด์ฌํ์ง๋ง ์ฅ์ ๋ค๋ ์กด์ฌํ๋ค.
1. ์์ฑ์์ ์ด๋ฆ(์๋ฏธ) ๋ถ์ฌ
public ์์ฑ์๋ ํด๋์ค์ ์ด๋ฆ๊ณผ ๋งค๊ฐ๋ณ์๋ง์ผ๋ก ๊ฐ์ฒด๋ฅผ ์์ฑํ์ง๋ง ์ ์ ํฉํฐ๋ฆฌ ๋ฉ์๋๋ ๋ฉ์๋ ์์ฒด์ ์ด๋ฆ์ ์ง์ ํ ์ ์์ด ๊ฐ๋ ์ฑ์ด ์ข์์ง๋ค.
class UUIDExample {
public static void main(String[] args) {
// ์ ์ ํฉํฐ๋ฆฌ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ์ฒด ์์ฑ
UUID randomUUID1 = UUID.randomUUID();
UUID nameUUID1 = UUID.nameUUIDFromBytes("example".getBytes());
// public ์์ฑ์๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ์ฒด ์์ฑ(์ค์ ์กด์ฌํ๋ ์ฝ๋x)
UUID randomUUID2 = new UUID();
UUID nameUUID2 = new UUID("example".getBytes());
}
}
๋จ์ํ public ์์ฑ์๋ฅผ ์ฌ์ฉํ์ฌ ์์ฑํ๋ค๋ฉด ์ ํํ ์ด๋ค ๊ฐ์ฒด๋ฅผ ์์ฑํ๋์ง ์๊ธฐ ์ด๋ ค์ ์ ๊ฒ์ด๋ค. ๋๋ฌธ์ ๋ง์ฝ ํ๋์ ํด๋์ค๊ฐ ์ฌ๋ฌ ๊ฐ์ ์์ฑ์๋ฅผ ๊ฐ์ ธ์ผ ํ๋ค๋ฉด pulbic ์์ฑ์๋ณด๋ค๋ ์ ์ ํฉํฐ๋ฆฌ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ฆ์ ์ง์ ํ๋ ๊ฒ์ด ์ข๋ค.
2. ํธ์ถ๋ ๋๋ง๋ค ์ธ์คํด์ค ์์ฑ ํ์ ์์
public ์์ฑ์๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ์ฒด๋ฅผ ์์ฑํ ๋๋ง๋ค ์๋ก์ด ์ธ์คํด์ค๋ฅผ ์์ฑํ์ง๋ง ์ ์ ํฉํฐ๋ฆฌ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฏธ๋ฆฌ ์์ฑํด๋ ์ธ์คํด์ค๋ฅผ ์ฌ์ฌ์ฉํ ์ ์๋ค.
class SingletonExample {
// ์ ์ ํฉํฐ๋ฆฌ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ์ธ์คํด์ค๋ฅผ ๊ด๋ฆฌ
private static SingletonExample instance;
// private ์์ฑ์๋ก ์ธ๋ถ์์ ์ธ์คํด์ค ์์ฑ ๋ฐฉ์ง
private SingletonExample() {
}
// ์ ์ ํฉํฐ๋ฆฌ ๋ฉ์๋
public static SingletonExample getInstance() {
if (instance == null) {
instance = new SingletonExample();
}
return instance;
}
public void doSomething() {
System.out.println("Singleton instance is here!");
}
}
class Main {
public static void main(String[] args) {
// ์ ์ ํฉํฐ๋ฆฌ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ์ธ์คํด์ค ์กฐํ
SingletonExample singleton = SingletonExample.getInstance();
// ์ธ์คํด์ค๋ฅผ ์ฌ๋ฌ ๋ฒ ๊ฐ์ ธ์๋ ๋์ผํ ์ธ์คํด์ค ๋ฐํ
SingletonExample anotherSingleton = SingletonExample.getInstance();
// ๋ ๊ฐ์ฒด๋ ์์ ๋์ผํ ๊ฐ์ฒด์ด๋ฏ๋ก true
System.out.println(singleton == anotherSingleton); // true
// ๊ฐ์ฒด ๋ฉ์๋ ํธ์ถ
singleton.doSomething();
}
}
์์ ๊ฐ์ด ์์ฑํ๋ฉด ์ธ์คํด์ค๋ฅผ ํ๋๋ก ์ ํํ ์ ์์ผ๋ฉฐ, ๋ํ ์ธ์คํด์ค๋ฅผ ๋ฏธ๋ฆฌ ์์ฑํด๋๊ณ ์ฌ์ฌ์ฉํ ์ ์์ด ๋ฉ๋ชจ๋ฆฌ ๋ญ๋น๋ฅผ ๋ฐฉ์งํ ์ ์๋ค.
์ด์ ๊ฐ์ด ์ธ์คํด์ค๋ฅผ ํ๋๋ก ์ ํํ๋ ๊ฒ์ ํ๋ผ์ด์จ์ดํธ ํจํด
์ ๊ทผ๊ฐ์ด ๋๋ ๊ธฐ๋ฒ์ด๋ค.
3. ๋ฐํ ํ์
์ ํ์ ํ์
๊ฐ์ฒด ๋ฐํ ๊ฐ๋ฅ
public ์์ฑ์๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ์ฒด๋ฅผ ์์ฑํ ๋๋ ํด๋น ํด๋์ค์ ์ธ์คํด์ค๋ง ๋ฐํํ ์ ์์ง๋ง ์ ์ ํฉํฐ๋ฆฌ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ํด๋น ํด๋์ค์ ํ์ ํ์ ๊ฐ์ฒด๋ฅผ ๋ฐํํ ์ ์๋ค.
interface Shape {
// ...
// ์ ์ ํฉํฐ๋ฆฌ ๋ฉ์๋๋ฅผ ์ด์ฉํ์ฌ Circle ๊ฐ์ฒด ์์ฑ
static Shape createCircle(double radius) {
return new Circle(radius);
}
// ์ ์ ํฉํฐ๋ฆฌ ๋ฉ์๋๋ฅผ ์ด์ฉํ์ฌ Rectangle ๊ฐ์ฒด ์์ฑ
static Shape createRectangle(double width, double height) {
return new Rectangle(width, height);
}
}
class Circle implements Shape {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
// ...
}
class Rectangle implements Shape {
private double width;
private double height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
// ...
}
class Main {
public static void main(String[] args) {
Shape circle = Shape.createCircle(10);
Shape rectangle = Shape.createRectangle(10, 20);
}
}
์์ ๊ฐ์ด ์ ์ ํฉํฐ๋ฆฌ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด Shape
์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ Circle
๊ณผ Rectangle
ํด๋์ค์ ์ธ์คํด์ค๋ฅผ ๋ฐํํ ์ ์๋ค.
์ค์ ๋ก Collection ํ๋ ์์ํฌ๋ ์ ์ ํฉํฐ๋ฆฌ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ ๋ฐํํ๋๋ฐ, ์ฌ์ฉ์๋ ํด๋น ์ธํฐํ์ด์ค์ ๊ตฌํ์ฒด๋ฅผ ์ ํ์ ์์ด ์ ์ ํฉํฐ๋ฆฌ ๋ฉ์๋๋ฅผ ํตํด ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ ์ฌ์ฉํ ์ ์๊ฒ ๋๋ค.
4. ์
๋ ฅ ๋งค๊ฐ๋ณ์์ ๋ฐ๋ผ ๋งค๋ฒ ๋ค๋ฅธ ํด๋์ค์ ๊ฐ์ฒด ๋ฐํ ๊ฐ๋ฅ
public ์์ฑ์๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ์ฒด๋ฅผ ์์ฑํ ๋๋ ํด๋น ํด๋์ค์ ์ธ์คํด์ค๋ง ๋ฐํํ ์ ์์ง๋ง ์ ์ ํฉํฐ๋ฆฌ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ์
๋ ฅ ๋งค๊ฐ๋ณ์์ ๋ฐ๋ผ ๋ค๋ฅธ ํด๋์ค์ ๊ฐ์ฒด๋ฅผ ๋ฐํํ ์ ์๋ค.
์ค์ ๋ก EnumSet
ํด๋์ค์ ์ ์ ํฉํฐ๋ฆฌ ๋ฉ์๋๋ ์
๋ ฅ ๋งค๊ฐ๋ณ์์ ๋ฐ๋ผ RegularEnumSet
(์์ 64๊ฐ ์ดํ)๊ณผ JumboEnumSet
(์์ 64๊ฐ ์ด๊ณผ)์ ์ธ์คํด์ค๋ฅผ ๋ฐํํ๋ค.
์๋๋ ๋งค๊ฐ๋ณ์ ๋ฌธ์์ด์ ์
๋ ฅ๋ฐ์ ํด๋น ๋ฌธ์์ด์ ํด๋นํ๋ Shape
์ธํฐํ์ด์ค์ ๊ตฌํ์ฒด๋ฅผ ๋ฐํํ๋ ์์์ด๋ค.
interface Shape {
static Shape createShape(String shapeType) {
if (shapeType == null) {
return null;
}
if (shapeType.equalsIgnoreCase("CIRCLE")) {
return new Circle();
} else if (shapeType.equalsIgnoreCase("RECTANGLE")) {
return new Rectangle();
}
return null;
}
void draw();
}
class Circle implements Shape {
@Override
public void draw() {
System.out.println("Circle");
}
}
class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Rectangle");
}
}
public class test {
public static void main(String[] args) {
Shape circle = Shape.createShape("circle");
circle.draw();
Shape rectangle = Shape.createShape("rectangle");
rectangle.draw();
}
}
3๋ฒ๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ํด๋ผ์ด์ธํธ๋ ํด๋น ์ธํฐํ์ด์ค์ ๊ตฌํ์ฒด๋ฅผ ์ ํ์ ์์ด ์ ์ ํฉํฐ๋ฆฌ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ ์ฌ์ฉํ ์ ์๋ ์ฅ์ ์ ๊ฐ์ง๊ฒ ๋๋ค.
5. ์ ์ ํฉํฐ๋ฆฌ ๋ฉ์๋๋ฅผ ์์ฑํ๋ ์์ ์๋ ๋ฐํํ ๊ฐ์ฒด์ ํด๋์ค๊ฐ ์กด์ฌํ์ง ์์๋ ๋จ
public ์์ฑ์๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ์ฒด๋ฅผ ์์ฑํ ๋๋ ํด๋น ํด๋์ค๊ฐ ๋ฐ๋์ ์กด์ฌํด์ผ ํ์ง๋ง ์ ์ ํฉํฐ๋ฆฌ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ํด๋น ํด๋์ค๊ฐ ์กด์ฌํ์ง ์์๋ ๋๋ค.
์ด๋ฐ ํน์ง์ ์๋น์ค ์ ๊ณต์ ํ๋ ์์ํฌ(Service Provider Framework)๋ฅผ ๋ง๋๋ ๊ทผ๊ฐ์ด ๋๋ค.
๋ํ์ ์ธ ์๋น์ค ์ ๊ณต์ ํ๋ ์์ํฌ๋ก๋ JDBC๊ฐ ์๋๋ฐ, ๊ทธ ์ค DriverManager
ํด๋์ค์ ์ค์ ๊ตฌํ ์ฝ๋๋ฅผ ์ผ๋ถ ๊ฐ์ ธ์ ๋ณด๋ฉด ์๋์ ๊ฐ๋ค.
// Connection.java
public interface Connection extends Wrapper, AutoCloseable {
// ...
}
// Driver.java
public interface Driver {
// ...
}
// DriverManager.java
public class DriverManager {
// List of registered JDBC drivers
private static final CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<>();
// ...
/* Prevent the DriverManager class from being instantiated. */
private DriverManager() {
}
public static void registerDriver(java.sql.Driver driver,
DriverAction da)
throws SQLException {
/* Register the driver if it has not already been added to our list */
if (driver != null) {
registeredDrivers.addIfAbsent(new DriverInfo(driver, da));
} else {
// This is for compatibility with the original DriverManager
throw new NullPointerException();
}
println("registerDriver: " + driver);
}
@CallerSensitive
public static Connection getConnection(String url)
throws SQLException {
java.util.Properties info = new java.util.Properties();
return (getConnection(url, info, Reflection.getCallerClass()));
}
// Worker method called by the public getConnection() methods.
private static Connection getConnection(
String url, java.util.Properties info, Class<?> caller) throws SQLException {
// ...
for (DriverInfo aDriver : registeredDrivers) {
// If the caller does not have permission to load the driver then
// skip it.
if (isDriverAllowed(aDriver.driver, callerCL)) {
try {
println(" trying " + aDriver.driver.getClass().getName());
Connection con = aDriver.driver.connect(url, info);
if (con != null) {
// Success!
println("getConnection returning " + aDriver.driver.getClass().getName());
return (con);
}
} catch (SQLException ex) {
if (reason == null) {
reason = ex;
}
}
} else {
println(" skipping: " + aDriver.driver.getClass().getName());
}
}
// if we got here nobody could connect.
if (reason != null) {
println("getConnection failed: " + reason);
throw reason;
}
println("getConnection: no suitable driver found for " + url);
throw new SQLException("No suitable driver found for " + url, "08001");
}
}
์ ์ฝ๋์์ ํ์ธํ ์ ์๋ ๊ฒ์ ์ ๋ฆฌํ๋ฉด ์๋์ ๊ฐ๋ค.
private ์์ฑ์๋ก ์ธ๋ถ์์ ์ธ์คํด์ค ์์ฑ ๋ฐฉ์ง
ArrayList๋ก ๊ฐ์ฒด๋ค์ ๊ด๋ฆฌ
registerDriver() ๋ฉ์๋ ํ๋ผ๋ฏธํฐ์ Driver ์ธํฐํ์ด์ค(= ์๋น์ค ์ ๊ณต์ ์ธํฐํ์ด์ค)๋ฅผ ํตํด ๊ฐ์ฒด๋ฅผ ์์ฑ(= ์ ๊ณต์ ๋ฑ๋ก API)
getConnection() ๋ฉ์๋๋ฅผ ํตํด Connection ์ธํฐํ์ด์ค(= ์๋น์ค ์ธํฐํ์ด์ค)๋ฅผ ํตํด ๊ฐ์ฒด๋ฅผ ๋ฐํ(= ์๋น์ค ์ ๊ทผ API)
์ด๋ฅผ ๊ฐ๋ตํ ํ๋ฉด ์๋์ ๊ฐ์ด ์ ๋ฆฌ ํ ์ ์๋ค.
// Service ์ธํฐํ์ด์ค: ๊ตฌํ์ฒด์ ๋์์ ์ ์
interface Service {
void execute();
}
// ์๋น์ค ์ ๊ณต์ ํด๋์ค 1
class ServiceProvider1 implements Service {
@Override
public void execute() {
// ๊ตฌํ ๋ด์ฉ
System.out.println("ServiceProvider1 ์คํ");
}
}
// ์๋น์ค ์ ๊ณต์ ํด๋์ค 2
class ServiceProvider2 implements Service {
@Override
public void execute() {
// ๊ตฌํ ๋ด์ฉ
System.out.println("ServiceProvider2 ์คํ");
}
}
class ServiceRegistry {
private static Map<String, Service> services = new HashMap<>();
// ์๋น์ค ์ ๊ณต์ ๋ฑ๋ก API: ์ ๊ณต์๊ฐ ๊ตฌํ์ฒด๋ฅผ ๋ฑ๋กํ ๋ ์ฌ์ฉ
public static void registerService(String name, Service service) {
services.put(name, service);
}
// ์๋น์ค ์ ๊ทผ API: ํด๋ผ์ด์ธํธ๊ฐ ์๋น์ค์ ์ธ์คํด์ค๋ฅผ ์ป์ ๋ ์ฌ์ฉ
public static Service getService(String name) {
return services.get(name);
}
}
์ ์ ํฉํฐ๋ฆฌ ๋ฉ์๋์ ๋จ์
1. private ์์ฑ์๋ง ์กด์ฌํ๋ฉด ํ์ ํด๋์ค๋ฅผ ๋ง๋ค ์ ์์ด ์์์ด ๋ถ๊ฐ๋ฅ
public class Parent {
private Parent() {
}
public static Parent createInstance() {
return new Parent();
}
}
public class Child extends Parent { // ์ปดํ์ผ ์ค๋ฅ, ์์ ๋ถ๊ฐ๋ฅ
}
์ด๋ ๋จ์ ์ด์ง๋ง, ์์๋ณด๋ค๋ ์ปดํฌ์ง์ ์ ์ฌ์ฉํ๋๋ก ์ ๋ํ๊ณ ๋ถ๋ณ ํ์ ์ผ๋ก ๋ง๋ค ์ ์์ด ๋ถ๋ณ์ฑ์ ๋ณด์ฅํ ์ ์๋ ์ฅ์ ์ด ์๋ค.
2. ์ ์ ํฉํฐ๋ฆฌ ๋ฉ์๋์ ์ด๋ฆ์ ์์์ผ ํจ
์์ฑ์๋ ํด๋์ค์ ์ด๋ฆ๊ณผ ๋์ผํ์ง๋ง ์ ์ ํฉํฐ๋ฆฌ ๋ฉ์๋๋ ์ด๋ฆ์ ์ง์ ํ ์ ์๊ธฐ ๋๋ฌธ์ ํด๋น ๋ฉ์๋์ ์ด๋ฆ์ ์์์ผ ํ๋ค. ์ด๋ฌํ ๋จ์ ์์ด ๋๋ฆฌ ์๋ ค์ง ๋ค์ด๋ฐ ๊ท์ ์ ํตํด ๋ฌธ์ ๋ฅผ ์ํํ๊ณ ์๋ค.
from
๋งค๊ฐ๋ณ์๋ฅผ ํ๋ ๋ฐ์์ ํด๋น ํ์ ์ ์ธ์คํด์ค๋ฅผ ๋ฐํํ๋ ํ๋ณํ ๋ฉ์๋
Date d = Date.from(instant);
of
์ฌ๋ฌ ๋งค๊ฐ๋ณ์๋ฅผ ๋ฐ์์ ์ ํฉํ ํ์ ์ ์ธ์คํด์ค๋ฅผ ๋ฐํํ๋ ์ง๊ณ ๋ฉ์๋
Set<Rank> faceCards = EnumSet.of(JACK, QUEEN, KING);
valueOf
from๊ณผ of์ ๋ ์์ธํ ๋ฒ์
BigInteger prime = BigInteger.valueOf(Integer.MAX_VALUE);
instance | getInstance
๋งค๊ฐ๋ณ์๋ก ๋ช ์ํ ์ธ์คํด์ค๋ฅผ ๋ฐํํ์ง๋ง, ๊ฐ์ ์ธ์คํด์ค์์ ๋ณด์ฅํ์ง ์์
StackWalker luke = StackWalker.getInstance(options);
create | newInstance
๋งค๋ฒ ์๋ก์ด ์ธ์คํด์ค ์์ฑ ๋ณด์ฅ
Object newArray = Array.newInstance(classObject, arrayLen);
getType
getInstance์ ๊ฐ์ผ๋, ์์ฑํ ํด๋์ค๊ฐ ์๋ ๋ค๋ฅธ ํด๋์ค์ ํฉํฐ๋ฆฌ ๋ฉ์๋๋ฅผ ์ ์ํ ๋ ์ฌ์ฉ
FileStore fs = Files.getFileStore(path);
newType
newInstance์ ๊ฐ์ผ๋, ์์ฑํ ํด๋์ค๊ฐ ์๋ ๋ค๋ฅธ ํด๋์ค์ ํฉํฐ๋ฆฌ ๋ฉ์๋๋ฅผ ์ ์ํ ๋ ์ฌ์ฉ
BufferedReader br = Files.newBufferedReader(path);
type
getType๊ณผ newType์ ๊ฐ๊ฒฐํ ๋ฒ์
List<Complaint> litany = Collections.list(legacyLitany);
Last updated
Was this helpful?