diff --git "a/\352\260\235\354\262\264\354\203\235\354\204\261/3\354\243\274\354\260\250-\355\224\204\353\241\234\355\206\240\355\203\200\354\236\205/summary/code.md" "b/\352\260\235\354\262\264\354\203\235\354\204\261/3\354\243\274\354\260\250-\355\224\204\353\241\234\355\206\240\355\203\200\354\236\205/summary/code.md" new file mode 100644 index 0000000..8536d6c --- /dev/null +++ "b/\352\260\235\354\262\264\354\203\235\354\204\261/3\354\243\274\354\260\250-\355\224\204\353\241\234\355\206\240\355\203\200\354\236\205/summary/code.md" @@ -0,0 +1,104 @@ +## Java +```java +public class Order implements Cloneable{ + private Orderer orderer; + private long orderIdx; + private long totalAmount; + private long lastAmount; + private long giftCouponPrice; + private long giftCouponUsedAmount; + private int discountRate; + private LocalDateTime expiryDt; + private LocalDateTime earliesstDt; + + @Override + public Order clone() throws CloneNotSupportedException { + return (Order) super.clone(); //Object의 clone()이용해서 복제후 Object에서 Order로 클래스 형변환 + } +} + +public class Client { + public static void main(String[] args) throws CloneNotSupportedException { + Order order1 = new Order(); + Order order2 = order1.clone(); + + System.out.println(order1 == order2); //false + System.out.println(order1.equals(order2)); //false + } +} +``` +자바에서는 객체를 복제할 수 있도록 최상위 클래스인 Object에서 `clone()`를 지원한다. 하지만 Object의 clone을 이용하기 위해서는 Cloneable을 implements해야만 사용이 가능하다. + +또한, 객체간의 동등성을 판단하기 위해 String의 equals() 처럼 object의 equals()를 이용하면 기대했던 값과는 다르게 `false` 가 반환된다.
이는 Object의 equals()는 `==`를 통해 비교하기 때문에 동일성비교와 같은 결과를 보여주는 것이고, String의 equals()는 값만을 비교하도록 재정의 했기 때문에 동등성 비교가 가능한 것이다. + +따라서 객체의 동등성을 비교하고 싶다면 `equals()`를 재정의 해주면 된다. + +```java +public class Order implements Cloneable{ + private Orderer orderer; + private long orderIdx; + private long totalAmount; + private long lastAmount; + private long giftCouponPrice; + private long giftCouponUsedAmount; + private int discountRate; + private LocalDateTime expiryDt; + private LocalDateTime earliesstDt; + + @Override + public Order clone() throws CloneNotSupportedException { + return (Order) super.clone(); //Object의 clone()이용해서 복제후 Object에서 Order로 클래스 형변환 + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Order)) return false; + Order order = (Order) o; + return orderIdx == order.orderIdx && totalAmount == order.totalAmount && lastAmount == order.lastAmount && giftCouponPrice == order.giftCouponPrice && giftCouponUsedAmount == order.giftCouponUsedAmount && discountRate == order.discountRate && Objects.equals(orderer, order.orderer) && Objects.equals(expiryDt, order.expiryDt) && Objects.equals(earliesstDt, order.earliesstDt); + } + + @Override + public int hashCode() { + return Objects.hash(orderer, orderIdx, totalAmount, lastAmount, giftCouponPrice, giftCouponUsedAmount, discountRate, expiryDt, earliesstDt); + } +} + +public class Client { + public static void main(String[] args) throws CloneNotSupportedException { + Order order1 = new Order(); + Order order2 = order1.clone(); + + System.out.println(order1 == order2); //false + System.out.println(order1.equals(order2)); //true + } +} +``` + +
+ +## PHP +```php +class Order{ + private $orderer; + private $orderIdx; + private $totalAmount; + private $lastAmount; + private $giftCouponPrice; + private $giftCouponUsedAmount; + private $discountRate; + private $expiryDt; + private $earliesstDt; +} + +class client extends PHPUnit\Framework\TestCase{ + function test_clone객체비교() { + $order1 = new Order(); + $order2 = clone $order1; + + $this->assertFalse($order == $order2); + $this->assertTrue($order === $order3); + } +} +``` +php는 `clone`이라는 키워드로 객체 복제를 지원하고 있으며, `==`,`===` 연산자로 동일성, 동등성을 비교해보면 복제된 객체와 동등하지만 동일하지는 않게 복제가 되는 것을 볼 수 있다. \ No newline at end of file diff --git "a/\352\260\235\354\262\264\354\203\235\354\204\261/3\354\243\274\354\260\250-\355\224\204\353\241\234\355\206\240\355\203\200\354\236\205/summary/\353\270\214\353\246\277\354\247\200 \355\214\250\355\204\264 \354\240\225\353\246\254.md" "b/\352\260\235\354\262\264\354\203\235\354\204\261/3\354\243\274\354\260\250-\355\224\204\353\241\234\355\206\240\355\203\200\354\236\205/summary/\353\270\214\353\246\277\354\247\200 \355\214\250\355\204\264 \354\240\225\353\246\254.md" new file mode 100644 index 0000000..d490758 --- /dev/null +++ "b/\352\260\235\354\262\264\354\203\235\354\204\261/3\354\243\274\354\260\250-\355\224\204\353\241\234\355\206\240\355\203\200\354\236\205/summary/\353\270\214\353\246\277\354\247\200 \355\214\250\355\204\264 \354\240\225\353\246\254.md" @@ -0,0 +1,152 @@ +# 프로토타입 패턴 + +> **원본 객체를 새로운 객체로 복사**하여 사용하는 패턴 + +![](https://refactoring.guru/images/patterns/diagrams/prototype/structure.png) + +**Prototype**: clone 메소드를 선언되어있는 인터페이스 + +**Concrete Prototype**: 실제로 클론 메소드를 구현하는 클래스. + +## 프로토타입은 언제 사용되는가? + +- 다수의 객체를 많이 만들고 싶은 경우 + +## 프로토타입 패턴 예제 코드 + +## Java + +```java +public class Order implements Cloneable{ + private Orderer orderer; + private long orderIdx; + private long totalAmount; + private long lastAmount; + private long giftCouponPrice; + private long giftCouponUsedAmount; + private int discountRate; + private LocalDateTime expiryDt; + private LocalDateTime earliesstDt; + + @Override + public Order clone() throws CloneNotSupportedException { + return (Order) super.clone(); //Object의 clone()이용해서 복제후 Object에서 Order로 클래스 형변환 + } +} + +public class Client { + public static void main(String[] args) throws CloneNotSupportedException { + Order order1 = new Order(); + Order order2 = order1.clone(); + + System.out.println(order1 == order2); //false + System.out.println(order1.equals(order2)); //false + } +} +``` + +자바에서는 객체를 복제할 수 있도록 최상위 클래스인 Object에서 `clone()`를 지원한다. 하지만 Object의 clone을 이용하기 위해서는 Cloneable을 implements해야만 사용이 가능하다. + +또한, 객체간의 동등성을 판단하기 위해 String의 equals() 처럼 object의 equals()를 이용하면 기대했던 값과는 다르게 `false` 가 반환된다. +이는 Object의 equals()는 `==`를 통해 비교하기 때문에 동일성비교와 같은 결과를 보여주는 것이고, String의 equals()는 값만을 비교하도록 재정의 했기 때문에 동등성 비교가 가능한 것이다. + +따라서 객체의 동등성을 비교하고 싶다면 `equals()`를 재정의 해주면 된다. + +```java +public class Order implements Cloneable{ + private Orderer orderer; + private long orderIdx; + private long totalAmount; + private long lastAmount; + private long giftCouponPrice; + private long giftCouponUsedAmount; + private int discountRate; + private LocalDateTime expiryDt; + private LocalDateTime earliesstDt; + + @Override + public Order clone() throws CloneNotSupportedException { + return (Order) super.clone(); //Object의 clone()이용해서 복제후 Object에서 Order로 클래스 형변환 + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Order)) return false; + Order order = (Order) o; + return orderIdx == order.orderIdx && totalAmount == order.totalAmount && lastAmount == order.lastAmount && giftCouponPrice == order.giftCouponPrice && giftCouponUsedAmount == order.giftCouponUsedAmount && discountRate == order.discountRate && Objects.equals(orderer, order.orderer) && Objects.equals(expiryDt, order.expiryDt) && Objects.equals(earliesstDt, order.earliesstDt); + } + + @Override + public int hashCode() { + return Objects.hash(orderer, orderIdx, totalAmount, lastAmount, giftCouponPrice, giftCouponUsedAmount, discountRate, expiryDt, earliesstDt); + } +} + +public class Client { + public static void main(String[] args) throws CloneNotSupportedException { + Order order1 = new Order(); + Order order2 = order1.clone(); + + System.out.println(order1 == order2); //false + System.out.println(order1.equals(order2)); //true + } +} +``` + +## PHP + +```php +class Order{ + private $orderer; + private $orderIdx; + private $totalAmount; + private $lastAmount; + private $giftCouponPrice; + private $giftCouponUsedAmount; + private $discountRate; + private $expiryDt; + private $earliesstDt; +} + +class client extends PHPUnit\Framework\TestCase{ + function test_clone객체비교() { + $order1 = new Order(); + $order2 = clone $order1; + + $this->assertFalse($order == $order2); + $this->assertTrue($order === $order3); + } +} +``` + +php는 `clone`이라는 키워드로 객체 복제를 지원하고 있으며, `==`,`===` 연산자로 동일성, 동등성을 비교해보면 복제된 객체와 동등하지만 동일하지는 않게 복제가 되는 것을 볼 수 있다. + +## 패턴의 장/단점 + +✅ 장점: + +- 구체적인 클래스로부터 커플링 없이 객체 복사 가능 +- 반복적인 초기화 코드를 제거해서, 프로토타입을 복제 할 수 있음. +- 복잡한 객체를 더 편리하게 생산할 수 있음 +- 복잡한 객체에 대한 사전 설정을 처리할때 상속 대신 사용 가능 + +🚨 단점: + +- 순환 참조가 있는 복잡한 객체를 복제하는 것은 매우 까다로울 수 있다. + +## 비슷한 패턴 + +- 많은 디자인패턴들이 **팩토리 메소드**(하위 클래스를 통해서 덜 복잡하고, 더 커스터마이징 가능하게)를 사용하는데, 추**상 팩토리 패턴, 프로토타입, 빌더**(더 유연하지만 좀 더 복잡한 형태)로 발전했다. + +- **추상팩토리** 클래스는 **팩토리 메소드**의 기반으로 설계되어있지만, **프로토타입**을 쓰면 이런 클래스들의 메소드들을 구성할 수 도 있다. + +- **프로토 타입**은 **커멘드 패턴**의 복사본을 기록에 저장해야할때 도움을 줍니다. + +- **데코레이터**와 **컴포짓 패턴**을 많이 사용한 설계의 경우 **프로토타입**을 사용하는게 많은 이점을 누릴 수 있다. 적용하면, 복잡한 구조를 처음부터 재구성할 필요가 없고, 복제 가능해진다. + +- **프로토타입**은 상속에 기반하지 않아서, 상속에 문제점이 없다. 반면에 복제할 객체의 초기화가 복잡해진다. 반대로 **팩토리 메소드**는 상속을 사용하지만, 초기화 단계가 필수적이지 않다. + +- **프로토타입**은 **메멘토 패턴**의 간단한 대체제가 될 수 있다. 이력에 저장하려는 상태인 객체가 매우 단순하고 외부 리소스에 대한 연결성이 없거나, 재연결성이 쉽게 되는 경우에 사용하는 것이 좋다. + +- **추상 팩토리 패턴, 빌더, 프로토타입**은 싱글톤으로 구현 가능하다.