继承与紧密耦合的构成

时间:2016-05-10 14:58:59

标签: java oop

我是一个完全的初学者,请原谅我的无知。 我创建了一个项目,我在某些类中使用了合成。 在我的Cinema类中,我有一个Schedule对象。

public class Cinema {        

private String name;        //set via constructor
private int seatCount;  // set in constructor  
private int rowCount;   // set in constructor  
private int cleanUpTime;        //set via constructor 
private LocalTime openTime = LocalTime.of(9, 30);        
private LocalTime closeTime = LocalTime.of(23, 59);      
private LocalTime peakTime = LocalTime.of(16, 30);   
private int costPerHour;        //set via constructor
private Schedule schedule = new Schedule(this);

//Constructors, other methods....
}

时间表属于电影院。它的某些方法需要一个Cinema对象。没有电影,时间表就不可能存在。

当阅读有关OOP的消息时,我被认为已经创建了一个现在与另一个类紧密耦合的类,这可能很糟糕。

因此我怎样才能改进这个设计?

我似乎有几个紧密耦合的类。例如预订舱和客户舱。预订有客户,客户包含他们所做的所有预订的清单。

我以为我正在使用合成而且那会很好但是现在我很困惑,因为我读到了关于耦合的内容。

请帮我理解。

4 个答案:

答案 0 :(得分:3)

必须有一些耦合。电影院和时间表并非完全独立。

  

时间表属于电影院。

到目前为止,非常好。

  

它的某些方法需要一个Cinema对象。

不。 Schedule对象应该能够独立存在。

由于您未提供任何代码,我将做出以下假设。

  • 电影院放映一部或多部电影。
  • 只要电影显示,电影就会有一周中每一天的日程安排。

所以这是一个Schedule类。

public class Schedule {
    private final Calendar showingTimestamp;

    public Schedule(Calendar showingTimestamp) {
        this.showingTimestamp = showingTimestamp;
    }

    public Calendar getShowingTimestamp() {
        return showingTimestamp;
    }

    public int getShowingWeekday() {
        return showingTimestamp.get(Calendar.DAY_OF_WEEK);
    }

}

Schedule类中唯一的字段包含显示日期和显示时间。我向您展示了如何使用Calendar方法获取工作日。

这是一个简单的电影课。

public class Movie {
    private final String name;

    private List<Schedule> showingList;

    public Movie(String name) {
        this.name = name;
        this.showingList = new ArrayList<>();
    }

    public void addShowing(Schedule schedule) {
        this.showingList.add(schedule);
    }

    public List<Schedule> getShowingList() {
        return Collections.unmodifiableList(showingList);
    }

    public String getName() {
        return name;
    }

}

Movie类了解Schedule类。 Schedule类不知道Movie类。

最后,这是Cinema课程。

public class Cinema {

    private final String name;

    private List<Movie> currentMovieList;

    public Cinema(String name) {
        this.name = name;
        this.currentMovieList = new ArrayList<>();
    }

    public void addCurrentMovie0(Movie movie) {
        this.currentMovieList.add(movie);
    }

    public void removeMovie(Movie oldMovie) {
        for (int index = currentMovieList.size() - 1; index >= 0; index--) {
            Movie movie = currentMovieList.get(index);
            if (movie.getName().equals(oldMovie.getName())) {
                currentMovieList.remove(index);
            }
        }
    }

    public List<Movie> getCurrrentMovieList() {
        return Collections.unmodifiableList(currentMovieList);
    }

    public String getName() {
        return name;
    }

}

Cinema类了解Movie类,间接了解Schedule类。 Movie类不了解Cinema类。

我希望这会有所帮助。

答案 1 :(得分:2)

可以在其中包含Cinema对象和Schedule对象列表。我认为一对多的关系。

答案 2 :(得分:1)

在合适的情况下,使用构图而不是继承确实是一个很好的设计实践。然而,你的问题并非如此:我没有看到基于遗产的合理替代你所形成的作品。

假设您正在尝试为可以区分IMAX电影院和其他电影院的系统设计类,具有一致的界面但行为不同。您可以考虑将ImaxCinema创建为Cinema的子类,并根据需要覆盖方法以自定义其行为:

class ImaxCinema extends Cinema {
    @Override
    int getScreenWidth() {
        // ...
    }
}

那是&#34;继承&#34;替代品。

另一方面,您可以创建一个接口ProjectorType,其实现StandardImax实现不同的行为。如果您为Cinema类提供类型ProjectorType的成员,那么您可以通过分配给该成员的对象的类来提供不同的行为:

class Cinema {
    ProjectorType projector;

    int getScreenWidth() {
        return projector.getScreenWidth();
    }
}

这是&#34;组合的一种常见形式&#34;替代品。

您的情况与继承与构成无关,因为不涉及行为的自定义。

避免类之间的紧密耦合是一个单独的考虑因素,是一个很好的设计原则。您的CinemaSchedule类确实是紧密耦合的,因为Schedule的构造函数需要Cinema参数这一点已经很明显了。

但是,请考虑Collections类的迭代器。每一个都固有地特定于特定的集合类,因为它必须导航该类的特殊内部数据结构才能正常工作。因此,每个迭代器的类都与相关的集合类紧密耦合,这是正常的。避免紧耦合通常一个好的原则并不意味着每个设计的质量都与耦合程度相反。

在您的特定情况下,我不太清楚您从Schedule课程中获得了什么好处,也不知道为什么它需要与Cinema紧密耦合。可能,您可以通过将Cinema成员移动到Schedule类,并通过调用Cinema的适当方法让Schedule访问它们来打破耦合。或者,将Schedule合并到Cinema而不是将其作为单独的类可能更有意义。如果这些都不可行,那么你可以考虑一直走下去,让Schedule成为Cinema的内部类。

答案 3 :(得分:0)

感觉良好,确实是紧耦合。通过创建一个新的接口来防止它,使得Schedule可能更容易重用。在界面中放置您要从Cinema使用的所有方法。 IDE的编译器将帮助您。对于那些接口方法,不要忘记在Cinema中添加@Overridable

public class Cinema implements Schedulable {
    private final Schedule schedule = new Schedule(this);

public class Schedule {
    public void Schedule(Schedulable schedulable) { // Instead of Cinema