Skip to content

Commit 771692c

Browse files
committed
Visitor updates
1 parent dcb57b0 commit 771692c

File tree

1 file changed

+48
-44
lines changed

1 file changed

+48
-44
lines changed

DesignPatterns/AppleStoreVisitor/README.md

Lines changed: 48 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,18 @@
3232

3333
#### Element:
3434

35-
Defines the protocol that accepts different types of discount visitors.
35+
- Defines the protocol that accepts different types of discount visitors.
36+
37+
- Products are will be accepting visitors, so we define each roles involved in the Element.
3638

3739
```swift
38-
protocol DiscountVisitorAccepting {
39-
func acceptVisitor(_ visitor: DiscountVisitor)
40+
public protocol Product {
41+
var id: String { get }
42+
var price: Double { get }
43+
}
44+
45+
public protocol VisitorAccepting {
46+
func accept<V: Visitor>(_ visitor: V) -> V.VisitorResult
4047
}
4148
```
4249

@@ -45,70 +52,68 @@ protocol DiscountVisitorAccepting {
4552
Concrete product types that accept a visitor according to the protocol defined above.
4653

4754
```swift
48-
struct MacBookProProduct: DiscountVisitorAccepting {
55+
struct MacBookProProduct: Product, VisitorAccepting {
4956
let id: String
5057
let price: Double
5158

52-
func acceptVisitor(_ visitor: DiscountVisitor) {
53-
visitor.visitMacBookPro(self)
59+
func accept<V: Visitor>(_ visitor: V) -> V.VisitorResult {
60+
visitor.visit(self)
5461
}
5562
}
5663

57-
struct VisionProProduct: DiscountVisitorAccepting {
64+
struct VisionProProduct: Product, VisitorAccepting {
5865
let id: String
5966
let price: Double
6067

61-
func acceptVisitor(_ visitor: DiscountVisitor) {
62-
visitor.visitVisionPro(self)
68+
func accept<V: Visitor>(_ visitor: V) -> V.VisitorResult {
69+
visitor.visit(self)
6370
}
6471
}
6572
```
6673

6774
#### Visitor:
6875

69-
Defines the discount calculation methods for each product type.
76+
- Defines the visitor protocol that will be implemented by concrete visitors.
77+
78+
- We are able to define the return type via the use of an associated type.
7079

7180
```swift
72-
protocol DiscountVisitor {
73-
func visitMacBookPro(_ macBookPro: MacBookProProduct)
74-
func visitVisionPro(_ visionPro: VisionProProduct)
81+
protocol Visitor {
82+
associatedtype VisitorResult
83+
func visit(_ product: Product) -> VisitorResult
7584
}
7685
```
7786

7887
#### Concrete visitors:
7988

80-
- Implements the discount calculations for each product type.
89+
- Concrete visitors that implement the visitor protocol.
8190

82-
- Education discount is 25%.
83-
84-
- Employee discount is 50%.
91+
- We have three discount types: education and employee discounts, and a description visitor.
8592

8693
```swift
87-
class EducationDiscountVisitor: DiscountVisitor {
94+
class EducationDiscountVisitor: Visitor {
95+
typealias VisitorResult = Double
8896
private let discountPercentage = 0.25
89-
private(set) var macBookProDiscount = 0.0
90-
private(set) var visionProDiscount = 0.0
91-
92-
func visitMacBookPro(_ macBookPro: MacBookProProduct) {
93-
macBookProDiscount = macBookPro.price * discountPercentage
94-
}
9597

96-
func visitVisionPro(_ visionPro: VisionProProduct) {
97-
visionProDiscount = visionPro.price * discountPercentage
98+
func visit(_ product: Product) -> Double {
99+
product.price * discountPercentage
98100
}
99101
}
100102

101-
class EmployeeDiscountVisitor: DiscountVisitor {
103+
class EmployeeDiscountVisitor: Visitor {
104+
typealias VistorResult = Double
102105
private let discountPercentage = 0.5
103-
private(set) var macBookProDiscount = 0.0
104-
private(set) var visionProDiscount = 0.0
105106

106-
func visitMacBookPro(_ macBookPro: MacBookProProduct) {
107-
macBookProDiscount = macBookPro.price * discountPercentage
107+
func visit(_ product: Product) -> Double {
108+
product.price * discountPercentage
108109
}
110+
}
109111

110-
func visitVisionPro(_ visionPro: VisionProProduct) {
111-
visionProDiscount = visionPro.price * discountPercentage
112+
class DescriptionVisitor: Visitor {
113+
typealias VisitorResult = String
114+
115+
func visit(_ product: Product) -> String {
116+
"Product with ID \(product.id) costs $\(product.price)"
112117
}
113118
}
114119
```
@@ -117,20 +122,19 @@ class EmployeeDiscountVisitor: DiscountVisitor {
117122

118123
```swift
119124
// Education discount for MacBook Pro
120-
121125
let educationDiscountVisitor = EducationDiscountVisitor()
122-
123126
let macBookProProduct = MacBookProProduct(id: "1", price: 1000.00)
124-
macBookProProduct.acceptVisitor(educationDiscountVisitor)
125-
126-
print(educationDiscountVisitor.macBookProDiscount) // 250.00
127+
let macBookProEducationDiscount = macBookProProduct.accept(educationDiscountVisitor)
128+
print(macBookProEducationDiscount) // 250.00
127129

128130
// Employee discount for Vision Pro
129-
130131
let employeeDiscountVisitor = EmployeeDiscountVisitor()
131-
132-
let visionProProduct = VisionProProduct(id: "1", price: 10000.00)
133-
visionProProduct.acceptVisitor(employeeDiscountVisitor)
134-
135-
print(employeeDiscountVisitor.visionProDiscount) // 5000.00
132+
let visionProProduct = VisionProProduct(id: "2", price: 10000.00)
133+
let visionProEmployeeDiscount = visionProProduct.accept(employeeDiscountVisitor)
134+
print(visionProEmployeeDiscount) // 5000.00
135+
136+
// Description for MacBook Pro
137+
let descriptionVisitor = DescriptionVisitor()
138+
let macBookProDescription = macBookProProduct.accept(descriptionVisitor)
139+
print(macBookProDescription) // Product with ID 1 costs $1000.0
136140
```

0 commit comments

Comments
 (0)