Java影院应用中如何为不同用户关联电影的独立附加项?
问题分析
你的核心问题在于把「电影本身的属性」和「用户针对该电影的个性化选择」混在了一起。Movie类代表的是影院里的固定电影资源(比如《搏击俱乐部》这部影片本身),它不应该绑定某个用户的附加项选择。当所有用户共享同一个Movie实例时,修改它的extras集合自然会影响所有人。
解决方案:引入中间关联类
我们需要一个中间类来封装「用户-电影-专属附加项」的关联关系,比如命名为MovieTicket(电影票),让每个用户的每部电影选择都对应一个独立的MovieTicket实例,附加项属于这个票,而非电影本身。
修改后的代码实现
1. 调整Movie类(仅保留电影固有属性)
移除附加项相关逻辑,让Movie只代表电影本身:
public class Movie { private String title, description; private int price, duration; public Movie(String title, int price, String description, int duration) { this.title = title; this.price = price; this.description = description; this.duration = duration; } // 添加getter方法,方便后续获取电影信息 public String getTitle() { return title; } public int getPrice() { return price; } }
2. 保留Extra类(无需修改)
public class Extra { private String name; private int price; public Extra(String name, int price) { this.name = name; this.price = price; } // 添加getter方法 public String getName() { return name; } public int getPrice() { return price; } }
3. 创建MovieTicket中间类
负责绑定用户选择的电影和专属附加项:
import java.util.ArrayList; import java.util.List; public class MovieTicket { private Movie movie; private List<Extra> selectedExtras; public MovieTicket(Movie movie) { this.movie = movie; this.selectedExtras = new ArrayList<>(); } // 给当前电影票添加附加项 public void addExtra(Extra extra) { selectedExtras.add(extra); } // 返回附加项副本,避免外部直接修改内部集合 public List<Extra> getSelectedExtras() { return new ArrayList<>(selectedExtras); } public Movie getMovie() { return movie; } }
4. 修改Person类(持有电影票而非电影)
让Person管理自己的MovieTicket集合:
import java.util.ArrayList; import java.util.List; public class Person { private String name; private int attendeesCount; private List<MovieTicket> movieTickets; public Person(String name, int attendeesCount) { this.name = name; this.attendeesCount = attendeesCount; this.movieTickets = new ArrayList<>(); } // 添加电影时创建对应的电影票,并返回供后续添加附加项 public MovieTicket addMovie(Movie movie) { MovieTicket ticket = new MovieTicket(movie); movieTickets.add(ticket); return ticket; } // 返回电影票副本,避免外部修改内部集合 public List<MovieTicket> getMovieTickets() { return new ArrayList<>(movieTickets); } public String getName() { return name; } }
5. 调整测试类逻辑
现在每个用户的电影附加项选择完全独立:
public class TestTheatre { public static void main(String[] args) { Movie fightClub = new Movie("Fight Club", 1000, null, 90); Movie theMatrix = new Movie("The Matrix", 2000, null, 80); Extra popcorn = new Extra("Popcorn", 500); Extra drink = new Extra("Drink", 400); Person john = new Person("John", 2); Person sam = new Person("Sam", 3); // John为《搏击俱乐部》选爆米花 MovieTicket johnFightClubTicket = john.addMovie(fightClub); johnFightClubTicket.addExtra(popcorn); john.addMovie(theMatrix); // Sam为《搏击俱乐部》选饮料 MovieTicket samFightClubTicket = sam.addMovie(fightClub); samFightClubTicket.addExtra(drink); // 验证结果 System.out.println(john.getName() + "的《搏击俱乐部》附加项:"); john.getMovieTickets().stream() .filter(ticket -> ticket.getMovie().getTitle().equals("Fight Club")) .flatMap(ticket -> ticket.getSelectedExtras().stream()) .forEach(extra -> System.out.println("- " + extra.getName())); System.out.println("\n" + sam.getName() + "的《搏击俱乐部》附加项:"); sam.getMovieTickets().stream() .filter(ticket -> ticket.getMovie().getTitle().equals("Fight Club")) .flatMap(ticket -> ticket.getSelectedExtras().stream()) .forEach(extra -> System.out.println("- " + extra.getName())); } }
运行结果
John的《搏击俱乐部》附加项: - Popcorn Sam的《搏击俱乐部》附加项: - Drink
通过这种设计,Movie类依然代表独立的电影资源,每个用户的个性化选择被封装在MovieTicket中,彻底解决了附加项全局共享的问题。
内容的提问来源于stack exchange,提问作者John Bowler
相关产品推荐
相关产品推荐

