就是一些if判断,这个很简单
看完需求,我大体思路如下:
一 需要抽象的对象:客户等级,客户等级价格,酒店,酒店销售策略,酒店星级,一周天数区间(因为是一周某几天对应一个价格,所以区间是一个对象)
二 以上对象的关系大体应该如下:
酒店应该有多种销售策略,因为工作日和周末的销售价格不一样,因此
销售策略应该包含一个天数区间和多个客户等级价格,因为某一个策略对应的是一周的几天,并且不同的客户等级对应的价格也不一样,因此
客户等级价格,应该包含一个客户等级和一个对应的价格,比如会员50元,普通客户100元,因此
天数区间应该包含多个天数
三.根据以上抽象的对象可以大体总结如下计算最优酒店的算法思路。
-输入:客户等级,开始时间,结束时间
-输出:酒店
1. 循环所有酒店,根据开始时间和结束时间还有客户等级算出每个酒店对应的价格,并且按照价格由低到高排序
2. 再按照酒店星级由高到低排序
3. 最后取第一个酒店即可
四.代码如下(代码主要采用Java8的流和新时间API,代码风格可能比较飘逸,请记得把JDK升到8)
测试类:
public class HotelTest {
public static void main(String[] args) {
test(CustomerLevel.NORMAL, LocalDate.of(2009, 3, 16), LocalDate.of(2009, 3, 18));
test(CustomerLevel.VIP, LocalDate.of(2016, 7, 31), LocalDate.of(2016, 8, 02));
}
public static void test(CustomerLevel customerLevel, LocalDate startDate, LocalDate endDate){
Hotel hotel = HotelSelector.chooseCheapest(customerLevel, startDate, endDate);
System.out.println(customerLevel.getName() + " " + startDate + "-" + endDate + "的最终选择的酒店:" + hotel.getName());
}
}
执行结果:
主体代码依次如下:
酒店类:
@Getter
@AllArgsConstructor
public enum Hotel {
// 如家
HomeInn("如家", HotelStar.THREE, Arrays.asList(
SaleStrategy.days(DaysInterval.wordDays).customerLevelPrices(
CustomerLevelPrice.level(CustomerLevel.NORMAL).price(110), CustomerLevelPrice.level(CustomerLevel.VIP).price(80)),
SaleStrategy.days(DaysInterval.weekend).customerLevelPrices(
CustomerLevelPrice.level(CustomerLevel.NORMAL).price(90), CustomerLevelPrice.level(CustomerLevel.VIP).price(80))
)),
// 七天
SevenDaysInn("七天", HotelStar.FOUR, Arrays.asList(
SaleStrategy.days(DaysInterval.wordDays).customerLevelPrices(
CustomerLevelPrice.level(CustomerLevel.NORMAL).price(160), CustomerLevelPrice.level(CustomerLevel.VIP).price(110)),
SaleStrategy.days(DaysInterval.weekend).customerLevelPrices(
CustomerLevelPrice.level(CustomerLevel.NORMAL).price(60), CustomerLevelPrice.level(CustomerLevel.VIP).price(50))
)),
// 汉庭
HanTing("汉庭", HotelStar.FIVE, Arrays.asList(
SaleStrategy.days(DaysInterval.wordDays).customerLevelPrices(
CustomerLevelPrice.level(CustomerLevel.NORMAL).price(210), CustomerLevelPrice.level(CustomerLevel.VIP).price(100)),
SaleStrategy.days(DaysInterval.weekend).customerLevelPrices(
CustomerLevelPrice.level(CustomerLevel.NORMAL).price(150), CustomerLevelPrice.level(CustomerLevel.VIP).price(40))
)),
;
// 酒店名字
private String name;
// 酒店星级
private HotelStar hotelStar;
// 酒店的销售策略集合
private List<SaleStrategy> saleStrategies;
public Integer getHotelStarValue(){
return this.hotelStar.getStarValue();
}
/**
* 根据一个集合的天数和客户等级算出所有天数该酒店的价格和
* @param dayOfWeekStream
* @param customerLevel
* @return
*/
public Integer getPrice(Stream<DayOfWeek> dayOfWeekStream, CustomerLevel customerLevel){
return dayOfWeekStream.map(dayOfWeek -> this.getPriceByDayOfWeek(dayOfWeek, customerLevel)).reduce(Integer::sum).get();
}
/**
* 根据当前的天数和客户等级,获取这一天,这个酒店的价格
* @param dayOfWeek
* @param customerLevel
* @return
*/
private Integer getPriceByDayOfWeek(DayOfWeek dayOfWeek, CustomerLevel customerLevel){
return this.saleStrategies.stream().filter(saleStrategy -> saleStrategy.getDaysInterval().contain(dayOfWeek))
.findFirst()
.map(saleStrategy -> saleStrategy.getCustomerLevelPrice(customerLevel))
.map(CustomerLevelPrice::getPrice)
.get();
}
}
酒店星级:
@Getter
@AllArgsConstructor
public enum HotelStar {
ONE(1),
TWO(2),
THREE(3),
FOUR(4),
FIVE(5);
private Integer starValue;
}
酒店销售策略:
@Getter
@Setter
public class SaleStrategy {
// 当前销售策略适应的天数区间
private DaysInterval daysInterval;
// 不同客户等级对应的价格集合
private List<CustomerLevelPrice> customerLevelPrices;
public static SaleStrategy days(DaysInterval daysInterval){
return new SaleStrategy(daysInterval);
}
public SaleStrategy customerLevelPrices(CustomerLevelPrice ... customerLevelPrices){
this.customerLevelPrices = Arrays.asList(customerLevelPrices);
return this;
}
public CustomerLevelPrice getCustomerLevelPrice(CustomerLevel customerLevel){
return this.customerLevelPrices.stream().filter(customerLevelPrice -> customerLevelPrice.getCustomerLevel().equals(customerLevel)).findFirst().get();
}
private SaleStrategy(DaysInterval daysInterval) {
this.daysInterval = daysInterval;
}
}
天数区间:
public class DaysInterval {
// 包含的一周哪些天
private List<DayOfWeek> days;
// 工作日区间(包括周一,周二,周三,周四,周五)
public static DaysInterval wordDays = of(DayOfWeek.MONDAY, DayOfWeek.TUESDAY, DayOfWeek.WEDNESDAY, DayOfWeek.THURSDAY, DayOfWeek.FRIDAY);
// 周末区间(包括周六,周日)
public static DaysInterval weekend = of(DayOfWeek.FRIDAY, DayOfWeek.SUNDAY);
public static DaysInterval of(DayOfWeek ... dayOfWeeks){
return new DaysInterval(Arrays.asList(dayOfWeeks));
}
public boolean contain(DayOfWeek dayOfWeek){
return this.days.contains(dayOfWeek);
}
private DaysInterval(List<DayOfWeek> days) {
this.days = days;
}
}
客户等级价格:
@Getter
public class CustomerLevelPrice {
// 客户等级
private CustomerLevel customerLevel;
// 对应的价格
private Integer price;
public static CustomerLevelPrice level(CustomerLevel customerLevel){
return new CustomerLevelPrice(customerLevel);
}
public CustomerLevelPrice price(Integer price){
this.price = price;
return this;
}
private CustomerLevelPrice(CustomerLevel customerLevel) {
this.customerLevel = customerLevel;
}
}
客户等级:
@Getter
@AllArgsConstructor
public enum CustomerLevel {
// 普通客户
NORMAL("普通客户"),
// VIP客户
VIP("会员客户");
private String name;
}
酒店选择器:
public class HotelSelector {
/**
* 根据当前客户级别,和客户准备入住酒店的开始时间和结束时间,筛选出当前最便宜的酒店
* @param customerLevel
* @param startDate
* @param endDate
* @return
*/
public static Hotel chooseCheapest(CustomerLevel customerLevel, LocalDate startDate, LocalDate endDate){
return Arrays.stream(Hotel.values())
// 先按照每个酒店的最终价格升序排列
.sorted(Comparator.comparing((Hotel hotel) -> hotel.getPrice(createStream(startDate, endDate), customerLevel))
// 若价格相等,再按照每个酒店的星级降序排列
.thenComparing(Comparator.comparing(Hotel::getHotelStarValue).reversed()))
// 排列后取第一个即可
.findFirst().get();
}
/**
* 将入店开始时间和离店时间转化为天数的流,方便后续计算
* @param startDate
* @param endDate
* @return
*/
public static Stream<DayOfWeek> createStream(LocalDate startDate, LocalDate endDate){
return Stream.iterate(startDate, localDate -> localDate.plusDays(1))
.limit(ChronoUnit.DAYS.between(startDate, endDate) + 1)
.map(LocalDate::getDayOfWeek);
}
}
五. 之所以有这么多的类,主要方便扩展,当前可快速扩展的点有:
1.销售区间可扩展,可自由选择周一到周末的任意几天为天数区间
2.客户等级可扩展,可扩展普通用户,黄金用户,白金用户等,不同用户也可以设置不同的价格
最后,本来代码在idea里写的挺漂亮的,不知道贴出来看着却这么丑...哎...
这个我觉的如果要实现完全达到自动化,这可能需要使用大数据知识让程序自动去判断吧!!!!