0

想象一个应用程序,其中您有一个名为 Transaction 的类来表示金融交易。

这些事务可以根据事务类的属性值和一些业务规则进行分类。

一个名为 TransactionType 的枚举表示此类分类的可能值:Type1Transaction、Type2Transaction、NotRelevant。

Type1Transactions 和 Type2Transactions 会被报告,因为它们有些可疑,NotRelevant 交易不会被报告。

这种分类只是为了报告交易而有趣,并不代表 Transaction 类的内在属性(这就是为什么 Transaction 类没有代表这种分类的属性)。

好吧,此时我们要编写一个类,其职责是确定给定事务的分类,我们称之为 TransactionClassificator。

它的接口公开了一个方法GetTransactionType(),它的返回值为TransactionType。最明显的实现如下:

public TransactionType GetTransactionType()
{
    if(IsType1Transaction())
        return TransactionType.Type1Transaction;

    if(IsType2Transaction())
        return TransactionType.Type2Transaction;

    return TransactionType.NotRelevant;
}

这种方法显然违反了 OCP 原则:它不接受修改,因为每次引入 enum TransactionType 的新值时都必须修改它。我不知道在这种特定情况下如何使用抽象来纠正违反 OCP 原则的问题。

感谢您的帮助。

恩里科

4

1 回答 1

0

使用 TypeReporter(或更合适的名称)。它的职责是根据从 Transaction 获得的数据确定交易类型:

interface TypeReporter {

    /**
     * Methods required for transaction to feed the data required for the 
     * business rules to determine the transacion type
     */

    public TransactionType determineType();
}

现在事务可以在 TypeReporter 的帮助下报告自己的类型:

interface Transaction {

    /** among other things **/

    public TransactionType reportType(TypeReporter reporter);

}

例如

class ConcreteTransaction implements Transaction {

    public TransactionType reportType(TypeReporter reporter) {
        reporter.hereIsThis(someProperty);
        reporter.andThat(someOtherProperty);

        return reporter.determineType();
    }

}

因此 Transaction 将类型确定委托给另一个对象。这样,如果出现新类型或用于确定类型的新策略,它就会关闭以供修改。如果发生这种情况,您将编写一个新的 TypeReporter。

编辑:为了使确定类型的方法更具抗更改性,您可以保留方便命名的类型,如下所示:

public enum TransactionType {
    Type1Transaction,
    Type2Transaction,
    NotRelevant
}

返回类型的方法可以是:

public TransactionType determineType() {
    //business logic to determine the type goes here
    //represent that type as a string (String determinedType)

    //now we check if that string is a valid enum value, if not returning NotRelevant
    try {
        return Choices.valueOf(determinedType + "Transaction");
    } catch (IllegalArgumentException ex) {  
        return TransactionType.NotRelevant;
    }
}

这样,如果 TransactionType 变得相关,您只需将其添加为新的 TransactionType 值,它将不再返回 NotRelevant。

于 2014-12-08T21:55:38.547 回答