정의 : 특정 데이터 구조에서 각 요소에 작용하는 특정 작업을 캡슐화합니다. 데이터 구조를 변경하지 않고 이러한 요소에 작용하는 새로운 작업을 정의 할 수 있습니다.
유형 : 행동 패턴
클래스 다이어그램 :
예:
예를 들어, 카트에 다른 유형의 상품을 추가하는 방법을 생각하고 결제를 클릭하면 모든 다른 상품에 대해 지불 할 수수료를 계산합니다. 이제 계산 로직은 이러한 다양한 유형의 상품의 가격을 계산하는 것입니다. 즉, 우리는이 논리를 방문자 모드를 통해 다른 클래스로 전송합니다. 이 방문자 패턴의 예를 구현합시다.
방문자 패턴을 구현하려면 가장 먼저해야 할 일은 다른 유형의 항목 (항목 요소)을 나타 내기 위해 쇼핑 카트에 추가 할 수있는 클래스를 만드는 것입니다.
itemelement.javapackage com.journalDev.design.visitor; public interface itemelement {public int accept (ShoppingCartvisitor Visitor);}수락 방법은 방문자를 매개 변수로 받아들입니다. 물론 여기에 자세한 제품을 지정하는 다른 방법이 있지만 간단하게하기 위해서는 여기에 너무 많은 세부 사항을 고려할 필요가 없으며 방문자 모드에만 중점을 둘 필요가 없습니다.
이제 다른 제품에 대한 엔티티 클래스를 만듭니다.
BOOK.java
com.journaldev.design.visitor; public class book emplements itemelement {private int price; 개인 문자열 isbnnumber; 공개 책 (int cost, string isbn) {this.price = cost; this.isbnnumber = isbn; } public int getPrice () {반환 가격; } public String getISBnnumber () {return isbnnumber; } @override public int acccep (ShoppingCartvisitor Visitor) {return visitor.visit (this); }}과일. 자바
com.journaldev.design.visitor; public class fruit emplements itemelement {private int priceperkg; 개인 INT 중량; 개인 문자열 이름; 공개 과일 (int pricekg, int wt, string nm) {this.priceperkg = pricekg; this.weight = wt; this.name = nm; } public int getPricePerkg () {return priceperkg; } public int getweight () {return weight; } public String getName () {return this.name; } @override public int acccep (ShoppingCartvisitor Visitor) {return visitor.visit (this); }} accept () 메소드의 구현은 엔티티 클래스에 있는데,이 클래스는 방문자의 visit () 메소드를 호출하여 현재 클래스 객체를 자체 매개 변수로 전달합니다.
여기서, 다른 유형의 상품에 사용되는 방문 () 방법은 방문자 인터페이스의 엔티티 클래스에서 구현됩니다.
ShoppingCartvisitor.java
com.journaldev.design.visitor; public interface shopping -cartvisitor {int visit (book book); int 방문 (과일 과일);}방문자 인터페이스가 구현되고 각 제품에 대한 자체 비용을 계산하는 논리가 구현됩니다.
ShoppingCartvisitorimpl.java
package com.journaldev.design.vesign.visitor; public class shoppingcartvisitorimpl은 쇼핑 카트비터 {@override public int visit (책) {int cost = 0; // 책 가격이 50보다 큰 경우 5 $ 할인을 적용합니다. } else cost = book.getPrice (); System.out.println ( "Book isbn ::"+book.getisbnnumber ()+"Cost ="+Cost); 반품 비용; } @override public int visit (fruit fruit) {int cost = fruit.getPricePerkg ()*fruit.getweight (); System.out.println (fruit.getName () + "cost =" + cost); 반품 비용; }}이제 프로그램에서 사용하는 방법을 살펴 보겠습니다.
ShoppingCartClient.java
package com.journaldev.design.vesign.visitor; public class shoppingcartclient {public static void main (String [] args) {itemelement [] items = new Book (20, "1234"), 새 책 (100, "5678"), 새로운 과일 (10, 2, "Banana"), 새로운 과일 (5, 5, "}; int total = calculatePrice (항목); System.out.println ( "총 비용 ="+총); } private static int calculatePrice (itemElement [] items) {ShoppingCartVisitor visitor = new ShoppingCartVisitorImpl (); int sum = 0; for (ItemElement 항목 : 항목) {sum = sum + item.accrect (방문자); } 반환 합계; }}위의 프로그램을 실행할 때는 다음과 같은 출력을 얻습니다.
Book isbn :: 1234 비용 = 20 책 isbn :: 5678 비용 = 95banana 비용 = 20 앱 비용 = 25total Cost = 160
여기서 구현은 모든 제품에 대한 accept () 메소드와 동일하지만 다를 수 있습니다. 예를 들어, 제품이 비어 있으면 논리적 검사를 수행 할 수 있으며 더 이상 visit () 메소드를 호출하지 않을 수 있습니다.
방문자 모드의 장점 :
단일 책임의 원칙을 준수하십시오 : 방문자 모드가 적용 가능한 모든 시나리오에서 요소 클래스의 방문자에 캡슐화되어야하는 작업은 요소 클래스 자체와 거의 관련이없고 휘발성이라는 작업이어야합니다. 한편으로, 방문자 모드의 사용은 단일 책임의 원칙을 준수하며, 다른 한편으로는 캡슐화 된 작업이 일반적으로 변동성이기 때문에 변화가 발생할 때 변화 부품의 확장은 요소 클래스 자체를 변경하지 않고 달성 될 수 있기 때문입니다.
우수한 확장 성 : 요소 클래스는 다른 방문자를 수락하여 다른 작업을 확장 할 수 있습니다.
방문자 모드에 대한 해당 시나리오 :
객체와 관련이없는 객체에 일부 작업이 있고 (또는 약한 관련) 및 이러한 작업이 객체를 오염시키는 것을 피하기 위해 방문자 모드를 사용하여 이러한 작업을 방문자에 캡슐화 할 수 있습니다.
객체 그룹에 유사한 작업이있는 경우 많은 수의 중복 코드를 피하기 위해 이러한 중복 작업을 방문자에 캡슐화 할 수도 있습니다.
그러나 방문자 모드는 그다지 완벽하지 않으며 치명적인 결함도 있습니다. 새로운 요소 클래스를 추가하는 것이 더 어렵습니다. 방문자 패턴의 코드를 통해 방문자 클래스에서 각 요소 클래스에 해당 처리 방법이 있음을 알 수 있습니다. 즉, 방문자 클래스 (방문자 클래스의 서브 클래스 또는 구현 클래스 포함)를 수정하기 위해 각 요소 클래스를 추가해야합니다. 즉, 요소 클래스의 수가 확실하지 않은 경우 방문자 모드를주의해서 사용해야합니다. 따라서 방문자 모드는 기존 기능을 리팩토링하는 데 더 적합합니다. 예를 들어, 프로젝트의 기본 기능이 결정되면 요소 클래스의 데이터가 기본적으로 결정되었으며 변경되지 않습니다. 변경 될 모든 것은 이러한 요소 내의 관련 작업입니다. 현재 방문자 모드를 사용하여 원래 코드를 리팩터링하여 각 요소 클래스를 수정하지 않고 원래 기능을 수정할 수 있습니다.
요약 :
Design Pattern의 저자 인 GOF는 방문자 모드를 설명합니다. 대부분의 경우 방문자 모드를 사용해야하지만 필요하면 필요하면 실제로 필요합니다. 물론 이것은 진짜 큰 사람들을위한 것입니다. 실제로 (적어도 내가있는 환경에서) 많은 사람들이 종종 디자인 패턴에 중독되어 있습니다. 디자인 패턴을 사용할 때 사용중인 패턴 이이 시나리오에 적합한 지 여부를 심각하게 고려하지 않지만 종종 객체 지향 디자인을 제어하는 능력을 보여주기를 원합니다. 프로그래밍 할 때 이러한 정신이 있다면 종종 디자인 패턴을 남용합니다. 따라서 디자인 패턴을 학습 할 때는 패턴의 적용 가능성을 이해해야합니다. 패턴을 이해하기 때문에 패턴을 사용하고 패턴을 사용하지 않기 때문에 패턴을 사용하지 않기 때문에 단점을 이해하기 때문입니다. 단점을 이해하지 못하기 때문에 패턴을 사용하는 대신, 장점을 이해하지 못하기 때문에 패턴을 사용하지 않기 때문입니다.