当看起来你需要通过超类引用访问子类方法时使用什么OOD模式?

时间:2015-10-25 03:33:36

标签: oop design-patterns

我正在研究类似的问题:有办事处和地区。有些(但不是全部)主管局都有销售信息。一些(但不是全部)地区有销售信息。拥有销售信息的办事处始终位于具有销售信息的区域,并且需要区域销售信息。没有销售信息的办公室,不关心他们所在的区域。那么,如何在面向对象的设计中最好地模拟这个?

显然,我们有OfficeDistrict个类,两者之间存在关系。最直接的实现是将销售信息成员直接包含在这些类中,并且当销售信息不存在时,这些成员为空。但是,对于我来说,将销售信息的实例作为SalesOfficeSalesDistrict的实例进行分区似乎更为OO,所以你会有这样的事情:

District <-------- Office
    ^                 ^
    |                 |
SalesDistrict      SalesOffice
  * GetSalesInfo     * GetSalesInfo
                     * PrintSalesInfo()

这是一个问题:SalesOffice.PrintSalesInfo需要调用SalesOffice和SalesDistrict的GeSalesInfo,并且将District转换为SalesDistrict似乎是一个坏主意。

必须有一个常用的设计模式可以在这里应用,以便:

  1. Office始终可以知道它属于哪个District,无论它属于哪个区域。
  2. 办事处和地区的一部分有销售信息。
  3. 包含销售信息的Office可以访问其所属的District的销售信息。
  4. 连连呢?我应该忘记继承并为IsSalesTypeOffice创建District标记,还是有更好的方法?

    [修改:请注意DistrictOffice返回的销售信息不是同一类型的信息]

2 个答案:

答案 0 :(得分:0)

我想说你不应该把办公室或地区分成有销售和缺课的班级。他们与销售的关系是&#34;有#34;而不是&#34;是&#34;。只需定义一个单独的销售对象,向办公室和区域分别提供对销售对象的引用,并向销售办公室提供对其父区的引用。这样,销售事物只有一个界面,无论他们是在区域还是办公室。

答案 1 :(得分:0)

根据您的解释,SalesDistrictSalesOffice似乎只是销售数据的持有者,并且不会自行添加任何额外的行为。我认为使用继承代表这不是一个好主意。

我认为将区域/办公室的销售信息作为实例变量是一种更好的方法。但是,您不需要使用isSalesType布尔标志来表示这一点。

如果您使用的是Java 8,那么Optional数据类型非常适合。这用于表示可以存在或不存在的数据。在这种情况下,您的学区类看起来像:

class District {
    ...
    Optional<SalesInfo> salesInfo;
    ...
}

每当您需要使用销售信息时,请使用以下方式将其打包:

if(salesInfo.isPresent()) {
    ...
}

要实例化销售信息对象,请使用:

Optional.of(new SalesInfo(..));

您可以使用Optional.empty()将其实例化为非销售区/ Office类中的空值。

编辑:

即使您所说的关于打印销售信息的行为很少,我仍然会继续执行上述实施,因为它在概念上更容易理解。在printSalesInfo类的Office方法内,您只需执行以下操作:

if(district.getSalesInfo().isPresent()) district.getSalesInfo().get().printSalesInfo();

但是,如果您仍然想完全避免这些检查,请点击此处:

class Office {
    private District district;
    // constructor
    public Office(District district) {
        this.district = district;
    }
}

class SalesOffice extends Office {
    private SalesDistrict district;
    private SalesInfo salesInfo;

    public SalesOffice(SalesDistrict district) {
        super(district);
        this.district = district;
    }

    public void printSalesInfo() {
        salesInfo.print();
        district.printSalesInfo();
    }
}

class District {
    ....
}

class SalesDistrict extends District {
    private SalesInfo salesInfo;
    public void printSalesInfo() {
        salesInfo.print();
    }
}

我们基本上保留对SalesDistrict类中SalesOffice对象的引用,尽管父类已经有引用。请注意,我们不会复制对象使用的内存。我们只是保留了额外的参考。当然,这不允许您构建具有非销售区域的销售办公室对象,但这无论如何都是您的假设之​​一。