refactoring : middle man - replace subclass with delegate

This commit is contained in:
haerong22
2022-04-09 21:35:28 +09:00
parent 852cfbe5af
commit 470ba9495e
9 changed files with 288 additions and 0 deletions

View File

@@ -0,0 +1,48 @@
package com.example.refactoring._18_middle_man._40_replace_subclass_with_delegate;
import java.time.DayOfWeek;
import java.time.LocalDateTime;
public class Booking {
protected Show show;
protected LocalDateTime time;
protected PremiumDelegate premiumDelegate;
public Booking(Show show, LocalDateTime time) {
this.show = show;
this.time = time;
}
public static Booking createBooking(Show show, LocalDateTime time) {
return new Booking(show, time);
}
public static Booking createPremiumBooking(Show show, LocalDateTime time, PremiumExtra extra) {
Booking booking = createBooking(show, time);
booking.premiumDelegate = new PremiumDelegate(booking, extra);
return booking;
}
public boolean hasTalkback() {
return (this.premiumDelegate != null) ? this.premiumDelegate.hasTalkback() :
this.show.hasOwnProperty("talkback") && !this.isPeakDay();
}
protected boolean isPeakDay() {
DayOfWeek dayOfWeek = this.time.getDayOfWeek();
return dayOfWeek == DayOfWeek.SATURDAY || dayOfWeek == DayOfWeek.SUNDAY;
}
public double basePrice() {
double result = this.show.getPrice();
if (this.isPeakDay()) result += Math.round(result * 0.15);
return (this.premiumDelegate != null) ? this.premiumDelegate.extendBasePrice(result) : result;
}
public boolean hasDinner() {
return this.premiumDelegate != null && this.premiumDelegate.hasDinner();
}
}

View File

@@ -0,0 +1,24 @@
package com.example.refactoring._18_middle_man._40_replace_subclass_with_delegate;
public class PremiumDelegate {
private Booking host;
private PremiumExtra extra;
public PremiumDelegate(Booking host, PremiumExtra extra) {
this.host = host;
this.extra = extra;
}
public boolean hasTalkback() {
return this.host.show.hasOwnProperty("talkback");
}
public double extendBasePrice(double result) {
return Math.round(result + this.extra.getPremiumFee());
}
public boolean hasDinner() {
return this.extra.hasOwnProperty("dinner") && !this.host.isPeakDay();
}
}

View File

@@ -0,0 +1,23 @@
package com.example.refactoring._18_middle_man._40_replace_subclass_with_delegate;
import java.util.List;
public class PremiumExtra {
private List<String> properties;
private double premiumFee;
public PremiumExtra(List<String> properties, double premiumFee) {
this.properties = properties;
this.premiumFee = premiumFee;
}
public double getPremiumFee() {
return premiumFee;
}
public boolean hasOwnProperty(String property) {
return this.properties.contains(property);
}
}

View File

@@ -0,0 +1,23 @@
package com.example.refactoring._18_middle_man._40_replace_subclass_with_delegate;
import java.util.List;
public class Show {
private List<String> properties;
private double price;
public Show(List<String> properties, double price) {
this.properties = properties;
this.price = price;
}
public boolean hasOwnProperty(String property) {
return this.properties.contains(property);
}
public double getPrice() {
return price;
}
}

View File

@@ -0,0 +1,32 @@
package com.example.refactoring._18_middle_man._40_replace_subclass_with_delegate._before;
import java.time.DayOfWeek;
import java.time.LocalDateTime;
public class Booking {
protected Show show;
protected LocalDateTime time;
public Booking(Show show, LocalDateTime time) {
this.show = show;
this.time = time;
}
public boolean hasTalkback() {
return this.show.hasOwnProperty("talkback") && !this.isPeakDay();
}
protected boolean isPeakDay() {
DayOfWeek dayOfWeek = this.time.getDayOfWeek();
return dayOfWeek == DayOfWeek.SATURDAY || dayOfWeek == DayOfWeek.SUNDAY;
}
public double basePrice() {
double result = this.show.getPrice();
if (this.isPeakDay()) result += Math.round(result * 0.15);
return result;
}
}

View File

@@ -0,0 +1,27 @@
package com.example.refactoring._18_middle_man._40_replace_subclass_with_delegate._before;
import java.time.LocalDateTime;
public class PremiumBooking extends Booking {
private PremiumExtra extra;
public PremiumBooking(Show show, LocalDateTime time, PremiumExtra extra) {
super(show, time);
this.extra = extra;
}
@Override
public boolean hasTalkback() {
return this.show.hasOwnProperty("talkback");
}
@Override
public double basePrice() {
return Math.round(super.basePrice() + this.extra.getPremiumFee());
}
public boolean hasDinner() {
return this.extra.hasOwnProperty("dinner") && !this.isPeakDay();
}
}

View File

@@ -0,0 +1,23 @@
package com.example.refactoring._18_middle_man._40_replace_subclass_with_delegate._before;
import java.util.List;
public class PremiumExtra {
private List<String> properties;
private double premiumFee;
public PremiumExtra(List<String> properties, double premiumFee) {
this.properties = properties;
this.premiumFee = premiumFee;
}
public double getPremiumFee() {
return premiumFee;
}
public boolean hasOwnProperty(String property) {
return this.properties.contains(property);
}
}

View File

@@ -0,0 +1,23 @@
package com.example.refactoring._18_middle_man._40_replace_subclass_with_delegate._before;
import java.util.List;
public class Show {
private List<String> properties;
private double price;
public Show(List<String> properties, double price) {
this.properties = properties;
this.price = price;
}
public boolean hasOwnProperty(String property) {
return this.properties.contains(property);
}
public double getPrice() {
return price;
}
}

View File

@@ -0,0 +1,65 @@
package com.example.refactoring._18_middle_man._40_replace_subclass_with_delegate;
import org.junit.jupiter.api.Test;
import java.time.LocalDateTime;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
class BookingTest {
@Test
void talkback() {
Show nonTalkbackShow = new Show(List.of(), 120);
Show talkbackShow = new Show(List.of("talkback"), 120);
LocalDateTime nonPeekDay = LocalDateTime.of(2022, 1, 20, 19, 0);
LocalDateTime peekDay = LocalDateTime.of(2022, 1, 15, 19, 0);
assertFalse(Booking.createBooking(nonTalkbackShow, nonPeekDay).hasTalkback());
assertTrue(Booking.createBooking(talkbackShow, nonPeekDay).hasTalkback());
assertFalse(Booking.createBooking(talkbackShow, peekDay).hasTalkback());
PremiumExtra premiumExtra = new PremiumExtra(List.of(), 50);
assertTrue(Booking.createPremiumBooking(talkbackShow, peekDay, premiumExtra).hasTalkback());
assertFalse(Booking.createPremiumBooking(nonTalkbackShow, peekDay, premiumExtra).hasTalkback());
}
@Test
void basePrice() {
Show lionKing = new Show(List.of(), 120);
LocalDateTime weekday = LocalDateTime.of(2022, 1, 20, 19, 0);
Booking booking = Booking.createBooking(lionKing, weekday);
assertEquals(120, booking.basePrice());
Booking premium = Booking.createPremiumBooking(lionKing, weekday, new PremiumExtra(List.of(), 50));
assertEquals(170, premium.basePrice());
}
@Test
void basePrice_on_peakDay() {
Show lionKing = new Show(List.of(), 120);
LocalDateTime weekend = LocalDateTime.of(2022, 1, 15, 19, 0);
Booking booking = Booking.createBooking(lionKing, weekend);
assertEquals(138, booking.basePrice());
Booking premium = Booking.createPremiumBooking(lionKing, weekend, new PremiumExtra(List.of(), 50));
assertEquals(188, premium.basePrice());
}
@Test
void hasDinner() {
Show lionKing = new Show(List.of(), 120);
LocalDateTime weekday = LocalDateTime.of(2022, 1, 20, 19, 0);
LocalDateTime weekend = LocalDateTime.of(2022, 1, 15, 19, 0);
PremiumExtra premiumExtra = new PremiumExtra(List.of("dinner"), 50);
assertTrue(Booking.createPremiumBooking(lionKing, weekday, premiumExtra).hasDinner());
assertFalse(Booking.createPremiumBooking(lionKing, weekend, premiumExtra).hasDinner());
assertFalse(Booking.createBooking(lionKing, weekend).hasDinner());
assertFalse(Booking.createBooking(lionKing, weekday).hasDinner());
}
}