์ผ | ์ | ํ | ์ | ๋ชฉ | ๊ธ | ํ |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- ์ธ๋ฑ์ค
- NoSQL
- ์๋ฃ๊ตฌ์กฐ
- index
- reverseํ๋ก์
- ๊น์๋ณต์ฌ
- binarySearch
- java
- ํ๋ก์์๋ฒ
- RDBMS
- ์ ๊ทํ
- mutable
- acid
- Database
- forwardํ๋ก์
- transaction
- ๋ฐฉ์ด์ ๋ณต์ฌ
- ๋ฐ์ดํฐ๋ฒ ์ด์ค
- ์์๋ณต์ฌ
- proxy
- ์กฐ์ธ
- immutable
- ๋ถ๋ณ๊ฐ์ฒด
- ์ด์งํ์
- ์๊ณ ๋ฆฌ์ฆ
- ERD
- Today
- Total
jacketList
๋๋ธ ๋์คํจ์น(Double Dispatch) ์ ๋ฐฉ๋ฌธ์ ํจํด(Visitor Pattren) ๋ณธ๋ฌธ
๋๋ธ ๋์คํจ์น(Double Dispatch) ์ ๋ฐฉ๋ฌธ์ ํจํด(Visitor Pattren)
ukkkk7 2024. 4. 16. 10:32๐ ๋๋ธ ๋์คํจ์น(Double Dispatch)
๋๋ธ ๋์คํจ์น๋ Dynamic Dispatch๋ฅผ ๋ ๋ฒ ํ๋ ๊ฒ์ ์๋ฏธํ๋ค.
situation
์ฐ์ฃผ์ ์ ํ์ฑ์ ์ฐฉ๋ฅ์ํค๋ ์ํฉ
์ฐ์ฃผ์ ์ ํ์ฑ์ ์ฐฉ๋ฅ์ํค๋ ๋ก์ง์ ์์ฑํ์ธ์
public interface Planet {
}
public class Mercury implements Planet {
}
public class Venus implements Planet {
}
public class Earth implements Planet {
}
public interface SpaceShip {
void landing(Planet planet);
void landing(Mercury planet);
void landing(Venus planet);
void landing(Earth planet);
}
๊ฐ๊ฐ์ ํ์ฑ๋ค์ ๋ง๋ค๊ณ spaceship ์ธํฐํ์ด์ค์์ landing๋ฉ์๋๋ฅผ ํ์ฑ๋ง๋ค ์ค๋ฒ๋ก๋ฉ ํ๋ค.
๊ฐ ํ์ฑ์ ์ฐฉ๋ฅ๋ฐฉ์์ ๋ค๋ฅด๊ฒ ์ค๊ณํด์ผ ํ๊ธฐ ๋๋ฌธ์ด๋ค.
์ด์ ์ ์ธํฐํ์ด์ค๋ฅผ ๋ฐํ์ผ๋ก ํ์ฌ์ ์ ๋ง๋ค์ด ๋ณด์
public class UkSpaceShip implements SpaceShip{
@Override
public void landing(Planet planet) {
System.out.println("๊ธฐ๋ณธ ์ฐฉ๋ฅ ๋ฐฉ์");
}
@Override
public void landing(Mercury planet) {
System.out.println("๋ํ ์ฅ๋น๋ฅผ ํผ์นฉ๋๋ค.");
System.out.println("๋ฐ์ผ๋ก ๊ณต๊ธฐ๋ฅผ ๋ฟ์ต๋๋ค.");
System.out.println("์์ฑ ์ฐฉ๋ฅ.");
}
@Override
public void landing(Venus planet) {
System.out.println("๋ํ์ฐ์ ํผ์นฉ๋๋ค.");
System.out.println("๊ธ์ฑ ์ฐฉ๋ฅ");
}
@Override
public void landing(Earth planet) {
System.out.println("๋ํ ์ฅ์น๋ฅผ ํผ์นฉ๋๋ค.");
System.out.println("์๋๊ฐ ์ค์ด๋ค๋ฉด ์ด์ ์์ด ๋ถ๋ฆฌ๋ฉ๋๋ค.");
System.out.println("๋ฌผ์ ๋จ์ด์ง๊ธธ ๊ธฐ๋ํฉ๋๋ค.");
System.out.println("์ง๊ตฌ ์ฐฉ๋ฅ.");
}
}
์ด์ ๋ง๋ค์ด์ง ํ์ฌ์ ์ Mainํจ์๋ฅผ ํตํด ์ฐฉ๋ฅ์์ผ๋ณด์
import java.util.ArrayList;
import java.util.List;
import org.example.planet.Earth;
import org.example.planet.Mercury;
import org.example.planet.Planet;
import org.example.planet.Venus;
public class Main {
public static void main(String[] args) {
SpaceShip ship = new UkSpaceShip();
// Mercury, Venus, Earch ์ธ์คํด์ค๋ฅผ planets์ ์ถ๊ฐํ๋ค.
List<Planet> planets = new ArrayList<>();
planets.add(new Mercury());
planets.add(new Venus());
planets.add(new Earth());
// ๊ฐ๊ฐ์ ํ์ฑ์ UkSpaceShip ์ธ์คํด์ค๋ฅผ landingํ๋ค.
for (Planet planet : planets) {
ship.landing(planet);
}
}
}
๊ฒฐ๊ณผ๋?
๋ถ๋ช ํ์ฑ๋ง๋ค ์ฐฉ๋ฅ ๋ก์ง์ ๋ค๋ฅด๊ฒ ์์ฑํ๋๋ฐ ์ ๋ถ ๊ธฐ๋ณธ ๋ก์ง์ผ๋ก ๋์ํ๊ณ ์๋ค.
์๋ํ๋ฉด ship.landing(planet) ์์ ํ๋ผ๋ฏธํฐ๋ก ๋๊ฒจ์ค planet์ planet ํ์ ์ ๊ฐ์ฒด์ด๊ธฐ ๋๋ฌธ์ด๋ค planet์ Mercury, Venus, Earth๊ฐ ๊ตฌํํ๊ณ ์์ง๋ง ์๋ฐ์ ์ ์ฅ์์๋ ์ด๋ฅผ ์ ์ ์๊ธฐ ๋๋ฌธ์ ์์๊ฐ์ด ๊ธฐ๋ณธ ๋ก์ง์ด ์คํ๋ ๊ฒ์ด๋ค.
์ด์๊ฐ์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ ๋ฐฉ๋ฒ์ผ๋ก 2๊ฐ์ง ๋ฐฉ๋ฒ์ด ์๋ค.
๐ก๋ฐฉ๋ฒ 1 - planet ๊ฐ์ฒด๊ฐ ๊ฐ ํ์ฑ์ ์ธ์คํด์ค์ธ์ง ํ์ธํ๊ธฐ
public class Main {
public static void main(String[] args) {
SpaceShip ship = new UkSpaceShip();
List<Planet> planets = new ArrayList<>();
planets.add(new Mercury());
planets.add(new Venus());
planets.add(new Earth());
for (Planet planet : planets) {
if (planet instanceof Mercury) {
ship.landing((Mercury) planet);
} else if (planet instanceof Venus) {
... ์๋ต
}
}
}
}
ํ์ง๋ง ์์๊ฐ์ด ์ฝ๋๋ฅผ ์์ฑํ๋ฉด ์๋ก์ด ํ์ฑ๊ฐ์ฒด๋ฅผ ๋ง๋ค์์ ๋ ์์ ์ ํด์ผํ ๋ฟ๋๋ฌ ์ฝ๋์ ์์ด ๋ง์์ง๋ ์๊ฐ ํท๊ฐ๋ฆฌ๋ ๋ฌธ์ ์ ์ด ์๊ธด๋ค.
๐ก๋ฐฉ๋ฒ 2 - Double Dispatch
public interface Planet {
// ์ถ์๋ฉ์๋๊ฐ ์ถ๊ฐ๋์์ต๋๋ค.
void landed(SpaceShip spaceShip);
}
import org.example.SpaceShip;
public class Mercury implements Planet {
@Override
public void landed(SpaceShip spaceShip) {
spaceShip.landing(this);
}
}
import org.example.SpaceShip;
public class Venus implements Planet {
@Override
public void landed(SpaceShip spaceShip) {
spaceShip.landing(this);
}
}
import org.example.SpaceShip;
public class Earth implements Planet {
@Override
public void landed(SpaceShip spaceShip) {
spaceShip.landing(this);
}
}
import java.util.ArrayList;
import java.util.List;
import org.example.planet.Earth;
import org.example.planet.Mercury;
import org.example.planet.Planet;
import org.example.planet.Venus;
public class Main {
public static void main(String[] args) {
SpaceShip ship = new UkSpaceShip();
List<Planet> planets = new ArrayList<>();
planets.add(new Mercury());
planets.add(new Venus());
planets.add(new Earth());
for (Planet planet : planets) {
// ship.landing(planet);
// ํด๋น ์ฝ๋๊ฐ ์ถ๊ฐ๋์์ต๋๋ค
planet.landed(ship);
System.out.println("\n");
}
}
}
๊ฒฐ๊ณผ๋?
์์๊ฐ์ด ๊ฐ ํ์ฑ๋ณ๋ก ๋ก์ง์ด ์คํ๋๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
์์ ์ ๊ตฌ์กฐ์ ๋๋ธ ๋์คํจ์น๋ฅผ ์ฌ์ฉํ ๊ตฌ์กฐ๋ฅผ ๋น๊ตํด๋ณด๋ฉด
์๋ฐ์์ ํ๋ผ๋ฏธํฐ๋ก ์ธํฐํ์ด์ค ํํ๋ฅผ ๋๊ฒจ์ฃผ๊ฒ ๋๋ฉด ๋ด๋ถ์์ instanceOf ๋ฉ์๋๋ฅผ ํตํด ์ปจ๋ฒํ ์ ํด์ค์ผ๋ง ํ๋ค.
๋๋ฌธ์ planet ๊ตฌํ์ฒด์์ landed๋ผ๋ ๋ฉ์๋๋ฅผ ๋ง๋ค์ด์ฃผ๊ณ landed๋ฉ์๋์์ SpaceShip ๊ฐ์ฒด์ landing๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด์ this๋ผ๋ ๊ฐ๊ฐ์ ํ์ฑ์ ๊ตฌํ์ฒด๋ก ๋๊ฒจ์ค๋ค.
์ด๋ฌํ ๋ฐฉ์์ Double Dispatch๋ผ๊ณ ํ๋ค.
์ด๋ฐ์์ผ๋ก ๊ตฌ์กฐ๋ฅผ ๊ฐ์ ธ๊ฐ๋ฉด
newSpaceShip์ด๋ผ๋ ์๋ก์ด ํด๋์ค๋ฅผ ๋ง๋ค์์ ๋๋ ์์ ํ ํ์๊ฐ ์์ด ํด๋์ค๋ง ๊ฐ์๋ผ์ฐ๋ฉด ๋๋ค.
import org.example.planet.Earth;
import org.example.planet.Mercury;
import org.example.planet.Planet;
import org.example.planet.Venus;
public class NewSpaceShip implements SpaceShip {
@Override
public void landing(Planet planet) {
System.out.println("๊ธฐ๋ณธ ์ฐฉ๋ฅ ๋ฐฉ์");
}
@Override
public void landing(Mercury planet) {
System.out.println("๊ธฐ์ ๋ฐ์ ์ผ๋ก ๊ทธ๋ฅ ์ฐฉ๋ฅํฉ๋๋ค");
System.out.println("์์ฑ ์ฐฉ๋ฅ");
}
@Override
public void landing(Venus planet) {
System.out.println("๊ธฐ์ ๋ฐ์ ์ผ๋ก ๊ทธ๋ฅ ์ฐฉ๋ฅํฉ๋๋ค");
System.out.println("๊ธ์ฑ ์ฐฉ๋ฅ");
}
@Override
public void landing(Earth planet) {
System.out.println("์ง๊ตฌ ์ฐฉ๋ฅ");
}
}
public class Main {
public static void main(String[] args) {
// SpaceShip ship = new UkSpaceShip();
SpaceShip ship = new NewSpaceShip();
List<Planet> planets = new ArrayList<>();
planets.add(new Mercury());
planets.add(new Venus());
planets.add(new Earth());
for (Planet planet : planets) {
planet.landed(ship);
System.out.println("\n");
}
}
}
Planet์ด ๋ฐ๋์ง ์๋๋ค๋ ์ ์ ํ์ ํ์ฌ์ ํด๋์ค๋ฅผ ์ผ๋ง๋ ์ง ๋ณ๊ฒฝํด๋ ๋ฌธ์ ๊ฐ ์๊ธฐ์ง ์๋๋ค. ์ด๋ฅผ ํตํด OCP ์์น์ ์งํฌ ์ ์๋ค.
๐ ๋ฐฉ๋ฌธ์ ํจํด(Visitor Pattern)
๋ฐฉ๋ฌธ์ ํจํด(Visitor Pattern)์ ๊ฐ์ฒด ์งํฅ ํ๋ก๊ทธ๋๋ฐ์์ ์ฌ์ฉ๋๋ ๋์์ธ ํจํด ์ค ํ๋๋ก ๊ฐ์ฒด์ ๊ตฌ์กฐ์ ๊ทธ ๊ตฌ์กฐ์์ ์ํ๋๋ ์์ ์ ๋ถ๋ฆฌํ์ฌ ๊ตฌํํ๋ ํจํด์ด๋ค.
๊ฐ์ฒด์ ๊ตฌ์กฐ์ ๊ตฌ์กฐ์์ ์ํ๋๋ ์์ ์ ๋ถ๋ฆฌํ์ฌ ๊ตฌํํจ์ผ๋ก์จ ๊ฐ์ฒด์ ํ์ฅ์ฑ๊ณผ ์ ์ฐ์ฑ์ ๋์ด๋๋ฉฐ ๊ฐ๋ฐฉ-ํ์ (OCP)์์น์ ์ ์ฉํ๋ ๋ฐฉ๋ฒ ์ค ํ๊ฐ์ง์ด๋ค.
Visitor ํจํด ์์
์๋ฐ์์ ๋ฐฉ๋ฌธ์ ํจํด์ ๊ตฌํํ๊ธฐ ์ํด์๋ ๋ค์๊ณผ ๊ฐ์ ์์๋ค์ด ํ์ํ๋ค.
- Element(์์) ์ธํฐํ์ด์ค : ๋ฐฉ๋ฌธ์๊ฐ ๋ฐฉ๋ฌธํ ๊ฐ์ฒด๋ค์ ๊ณตํต ์ธํฐํ์ด์ค์ด๋ค. accept๋ฉ์๋๋ฅผ ๊ฐ์ง๊ณ ์์ด์, ๋ฐฉ๋ฌธ์๊ฐ ์์ ์ ๋ฐฉ๋ฌธํ ์ ์๋๋ก ํ๋ค.
- ConcreteElement(๊ตฌ์ฒด์ ์ธ ์์) ํด๋์ค : Element ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ ํด๋์ค๋ค์ด๋ค. ๋ฐฉ๋ฌธ์๊ฐ ๋ฐฉ๋ฌธํ ์ค์ ๊ฐ์ฒด๋ค
- Visitor(๋ฐฉ๋ฌธ์) ์ธํฐํ์ด์ค : Element ๊ฐ์ฒด๋ค์ ๋ฐฉ๋ฌธํ๋ ๋ฉ์๋๋ค์ ์ ์ธํ ์ธํฐํ์ด์ค์ด๋ค.
- ConcreteVisitor(๊ตฌ์ฒด์ ์ธ ๋ฐฉ๋ฌธ์) ํด๋์ค : Visitor ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ ํด๋์ค๋ค์ด๋ค. Element ๊ฐ์ฒด๋ค์ ๋ฐฉ๋ฌธํ๋ ๊ตฌ์ฒด์ ์ธ ๋ฐฉ๋ฒ๋ค์ ๊ตฌํํ๋ค.
์์ ๋ค์ด์ด๊ทธ๋จ์ ์ฝ๋๋ก ๊ตฌํํ ์์ ๋ฅผ ์ดํด๋ณด์
public interface Visitor {
int visit(Book book);
int visit(Music music);
int visit(Movie movie);
}
๋จผ์ , ๋ฐฉ๋ฌธ์(Visitor) ์ธํฐํ์ด์ค๋ฅผ ์ ์ํด์ค๋ค. ์ด ์ธํฐํ์ด์ค๋ ๊ฐ๊ฐ์ ์ํ ํด๋์ค์์ ๊ตฌํ๋ visit ๋ฉ์๋๋ฅผ ์ ์ํ๋ค.
public interface Element {
int accept(Visitor visitor);
}
๊ฐ๊ฐ์ Element ์ํ ํด๋์ค(Book, Music, Movie)๋ฅผ ์ ์ํ๋ค. ๊ฐ ํด๋์ค๋ ๊ฐ๊ฒฉ(price) ์์ฑ์ ๊ฐ๊ณ ์์ผ๋ฉฐ, Visitor์ธํฐํ์ด์ค์์ ๊ตฌํํ visit ๋ฉ์๋๋ฅผ ์ ์ํ๋ค.
public class Book implements Element {
private int price;
public Book(int price) {
this.price = price;
}
public int getPrice() {
return price;
}
@Override
public int accept(Visitor visitor) {
return visitor.visit(this);
}
}
public class Music implements Element {
private int price;
public Music(int price) {
this.price = price;
}
public int getPrice() {
return price;
}
@Override
public int accept(Visitor visitor) {
return visitor.visit(this);
}
}
public class Movie implements Element {
private int price;
public Movie(int price) {
this.price = price;
}
public int getPrice() {
return price;
}
@Override
public int accept(Visitor visitor) {
return visitor.visit(this);
}
}
public class PriceCalculator implements Visitor {
@Override
public int visit(Book book) {
return book.getPrice();
}
@Override
public int visit(Music music) {
return music.getPrice() * 2;
}
@Override
public int visit(Movie movie) {
return movie.getPrice() * 3;
}
}
Visitor ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ ๊ฐ๊ฒฉ ๊ณ์ฐ Visitor ํด๋์ค๋ฅผ ์ ์ํ๋ค. ์ด ํด๋์ค๋ ๊ฐ๊ฐ์ ์ํ์ ๋ฐฉ๋ฌธํ์ฌ ๊ฐ๊ฒฉ์ ๊ณ์ฐํ๋ค.
public class Main {
public static void main(String[] args) {
Element book = new Book(10000);
Element music = new Music(5000);
Element movie = new Movie(15000);
Visitor visitor = new PriceCalculator();
int totalPrice = book.accept(visitor) + music.accept(visitor) + movie.accept(visitor);
System.out.println("book pirce = " + book.accept(visitor));
System.out.println("music pirce = " + music.accept(visitor));
System.out.println("movie pirce = " + movie.accept(visitor));
System.out.println("Total Price = " + totalPrice);
}
}
์คํ๊ฒฐ๊ณผ๋?
Book, Music, Movie ํด๋์ค์ ์ธ์คํด์ค๋ฅผ ์์ฑํ๊ณ , PriceCalculatorํด๋์ค์ ์ธ์คํด์ค๋ฅผ ์์ฑํ๋ค. ๊ฐ๊ฐ์ ์ํ ์ธ์คํด์ค์์๋ accept ๋ฉ์๋๋ฅผ ํธ์ถํ์ฌ PriceCalculator ํด๋์ค์ visit ๋ฉ์๋๋ฅผ ํธ์ถํ๋ค.
์ด๋ฐ์์ผ๋ก Visitor ํจํด์ ์ฌ์ฉํ๋ฉด, ์๋ก์ด ์ํ์ด ์ถ๊ฐ๋ ๋๋ง๋ค, ๊ฐ์ฒด ๊ตฌ์กฐ๋ฅผ ์์ ํ์ง ์๊ณ ๋ PriceCalculator ํด๋์ค์ visit ๋ฉ์๋๋ฅผ ์ถ๊ฐํ๊ฑฐ๋ ์์ ํจ์ผ๋ก์จ ๊ฐ๊ฒฉ ๊ณ์ฐ ๋ฐฉ์์ ๋ณ๊ฒฝํ ์ ์๋ค.
references
'Java' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Java] ์์ธ์ฒ๋ฆฌ (0) | 2024.05.07 |
---|---|
[Java] ์ธํฐํ์ด์ค(Interface) (1) | 2024.04.28 |
[Java] ์์(Inheritance) (1) | 2024.04.13 |
[Java] ํด๋์ค(Class) - ๋ฐฑ๊ธฐ์ ๋ผ์ด๋ธ ์คํฐ๋ (0) | 2024.04.10 |
[Java] ์ ๋ค๋ฆญ(Generic) (1) | 2023.12.11 |