想象一下一个应用程序,你有一个名为Transaction的类代表一个金融交易。
可以根据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原则:它不会因修改而关闭,因为每次引入枚举TransactionType的新值时都必须修改它。在这个特定的场景中,我无法弄清楚如何使用抽象来修复OCP原则违规。
感谢您的帮助。
恩里科
答案 0 :(得分: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);
}
e.g。
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。