现实世界中的设计模式

时间:2014-08-28 02:58:36

标签: java oop design-patterns

我正在从Head第一本书中学习设计模式,我理解其中的大多数。但是当我尝试在现实世界中应用时,它变得更加困难。在每个例子中,它都创建了很多子类。但是我们真的在实时项目中创建了这么多课程吗?

E.g。考虑银行账户的一个例子 方法1:

    Account {

    String name;
    double balance;
    operation1() {
    }
}


SavingAccount extends Account {
    // some extra fields and methods related to saving account 
    operation1() {
    }

}

CurrentAccount extends Account {
    // Some extra fields and methods related to current account.
    operation1() {
    }

}

当我使用数据库映射这些类时,使用Hibernate之一使用继承策略,例如,每个子类的表,我最终会有三个表。帐户,Saving_account和Current_account。 优点:我可以根据使用多态的对象类型调用operation1()。

缺点:更多的表和类。如果项目更复杂,更大,最终会有数千个课程。

方法2:

    Account {
    string name;
    double balance;
    string type;
    operation1() {
    }
}

我只需要一个名为Account的方法表。 “类型”字段将标识帐户的类型。

优势:只有1桌和班级。 缺点:我将失去面向对象的世界,我必须把所有条件都放在下面。

    if (type == saving) {
    // do this;
} else if (type == current) {
    // do that;
}

根据理论,方法1是正确且最好的。但目前在我的项目中,使用了方法2。我的项目不是银行业务。我把它作为简单的例子。

我知道这是一个非常基本的问题。但由于我目前的项目实施,我无法阻止自己提出这个问题。

编辑:方法1的可维护性比方法2更好。

3 个答案:

答案 0 :(得分:3)

继承等设计模式很难用它们的重要性来描述,因为需要一个非常大的项目才能实现它的强大功能。通常示例最终会出现以下内容:

class A {
}

class B extends A {
}

class C extends B {
}

class D extends A {
}

然后你会得到很多不那么真实的问题,例如foo()在它分别实施四次时真正引用的方法。

使用继承的动机是在类中将相似类型的事物组合在一起。一个基本的例子是,如果你想在一个列表中同时拥有一堆不同的对象。如果它们是所有不同的类型,则这是不可能的,但如果它们在继承层次结构中,则可以将它们组合在一起。

对于您的示例,您可以将每个Account对象放入单个列表中,无论对象实际位于哪个子类中。

List<Account> list = new ArrayList<Account> ();
list.add(new Account());
list.add(new SavingsAccount());
list.add(new CurrentAccount());

假设您要处理该列表中的所有内容。如果您有一个常用方法,则可以使用多态来使每个Account执行自己的特定操作:

for(Account a : list) {
   a.operation1();
}

比为每种类型的对象单独列出要简单得多,不是吗?然后,如果您想要制作更多类型的帐户,如果您扩展基础Account类,则不必为代码添加新列表和新循环。一切都可以保持原样。

使用继承还有助于使用其他人编写的代码。如果要向其他人编写的类添加内容,可以将其包含在包中,然后使用自己的类扩展它。这样你就不必进行大量的复制和粘贴,并浏览其他类的源代码。即使您只有.class文件,也可以扩展另一个类,而不是.java文件中的源代码。

所以继承的力量取决于你如何使用它。在一个小例子中,它并没有真正有意义。但是项目越大,它就越有意义。

答案 1 :(得分:1)

如前所述,这两种方法都是有效的,您解释的优点和缺点也是有效的。

但是,例如,如果您将此会计软件包(已编译的jar)作为要由其他人扩展的库,那么方法1是理想的,因为;

  1. 您不需要修改Account的任何源代码,只需扩展它,然后实现您自己的版本。例如: - FixedDepositAccount
  2. 不会破坏您的Account代码。
  3. 无需再次对Account.operation1()
  4. 进行测试

    但是如果你愿意分享源代码并愿意做上述步骤,那么最好使用方法2.

答案 2 :(得分:0)

在Java中,我们可以String type;(不是string type;),但更好的是Enum类型(这样我们可以添加货币市场帐户或白金首选储蓄帐户,可能没有重新实现调用者代码)。像,

 enum AccountType {
    CHECKING(0.005), SAVINGS(0.01), MMA(0.02);
    final double rate;

    private AccountType(double rate) {
        this.rate = rate;
    }
    public double getRate() {
        return this.rate;
    }
}

使用AccountType,您可以安全地使用==进行相等,而使用if (type == saving) {执行String则会遇到麻烦。那是

if (type == AccountType.CHECKING) {
} else if (type == AccountType.SAVINGS) {

将按照您的预期运作。最后,最好尽量避免使用if链,而是尽可能将您计划对帐户类型执行的操作封装到枚举中。例如,

Account acct = getAccount(accountNumber);
if (acct != null && acct.isValid()) {
  acct.balance += acct.balance * type.getRate();
}