You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 06:03:22