Java 封装和 OOP 最佳实践

标签 java oop encapsulation

我实现了一个名为 mobileCall 的类。我从此类创建了多个对象,并使用来自 XML 的值填充该对象的 String 变量,该 XML 具有针对特定人员的多个 mobileCall。我需要对该人调用的所有电话进行分组和统计(即国内电话:11 分钟;国际电话:15 分钟;数据:20 MB)

因此,我在类中实现了几个公共(public)方法来检查调用的类型以返回 true 或 false。在主类中,我调用这些方法来检查它们是否满足我对特定计数器进行计数的标准。

有人专业人士看到我的代码并说这不是一个好的做法,OOP 旨在消除这种“你是谁”的方法。并且有更好的方法来实现这种行为。我尝试通读 OOP 和 Encapsulation,但找不到更好的方法。不过我觉得他说的有道理。

代码示例

public class MobileCall {

    String callType;
    String callDuration;
    String callAmount;
    String callerID;
    String calleID;
    ....
    public boolean isNational(){

        if (callType.compareTo("National")==0)
            return true;
        else
            return false;
    }

    public boolean isInternational(){

        if (callType.compareTo("international")==0)
            return true;
        else
            return false;
    }
    ...
}

In Main Method

int nationalCounter;
int internationalCounter;
MobileCall mobileCall = new MobileCall();

if(mobileCall.isNational())
    nationalCounter = nationalCounter + mobileCall.getCallDuration();
else if (mobileCall.isInternational())
    internationalCounter = internationalCounter + mobileCall.getDuration();
....

最佳答案

private String callType;

....
public boolean isNational(){

    if (callType.compareTo("National")==0)
        return true;
    else
        return false;
}

public boolean isInternational(){

    if (callType.compareTo("international")==0)
        return true;
    else
        return false;
}

是相关代码。这就是要点(现在 callType 现在已被严格封装)。

三个月后,有人提示该程序占用了太多内存。您重新访问代码并认为字符串可能不是确定调用国籍的最佳方式,毕竟它要么是国际性的,要么不是国际性的,对吧?这意味着您最多需要一位来存储数据。

你做出改变

private boolean nationalCall;

然后更改使用此数据的方法

public boolean isNational() {
  return nationalCall;
}

public boolean isInternational() {
  return !nationalCall;
}

并且因为您正确封装了“国家调用数据”,所以您可以放心,您不再需要搜索程序的其余部分来确保程序的其他部分能够正常工作。更改的“效果”被“封装”在类的“接口(interface)”的“边界”处,该“接口(interface)”实际上是由许多“成员方法”实现的。

现在代码如下

if (mobileCall.isNational()) {
    nationalCounter = nationalCounter + mobileCall.getCallDuration();
} else if (mobileCall.isInternational()) {
    internationalCounter = internationalCounter + mobileCall.getDuration();
}

看起来很可疑。请注意,这段代码似乎非常关心不同类的数据和方法。或许是外部对类进行了管理,以至于行为定位错位了?

如果您将方法添加到“Call”类

public int getNationalMinutes() {
  if (national) {
    return callDuration;
  }
  return 0;
}

public int getInternationalMinutes() {
  if (!national) {
    return callDuration;
  }
  return 0;
}

然后您可以将累积代码减少到

while (Call call : client.getAllCalls()) {
  internationalMinutes += call.getInternationalMinutes();
  nationalMinutes += call.getNationalMinutes();
}

请注意,最后一点工作并不是严格数据意义上的 100% 封装,因为我们添加了接口(interface)项(方法);但它确实在行为意义上做了一些封装,因为我们不再需要根据一系列查询来确定通话记录是国际的还是国内的,从而确定类的内部状态。

对类进行一系列检查以确定如何使用类的日期是“Call”类外部行为的外部迁移。因此,将这种行为移回到类中可以被认为是对类行为的封装,与前面的示例不同,后者是对类数据的严格封装。

很多时候,人们忘记了类封装了数据行为。感谢您找到了一个很好的示例,其中两个封装点都可以在同一问题中呈现。

关于Java 封装和 OOP 最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19033724/

相关文章:

java - Hibernate更新对象的非引用字段

php - 现实生活中的依赖注入(inject)

c++ - 防止破坏封装

javascript - 关于对象的属性名称

java - 如何使用封装的相同方法实现多个子类?

oop - 封装、数据抽象和数据隐藏的精确解释

java - 如何读取 Google App Engine (JAVA) 中的文件

java - 除了 in 之外,还有其他工具可以查看本地 derby 数据库(文件夹)吗?

java - 如果每个线程都必须访问相同的数组,则会影响性能

Javascript:在该对象中调用对象方法