错过多态的机会
多态(Polymorphism)是OO的一条主要的基础思想。这个词源来希腊语,意思是多种(poly)形态(morph)。在编程中,多态是指一个特定的对象类或者方法类的多种形态,但多态并不简单地是变化的实现。细心使用,多态可以创建出细小的本地化执行上下文,让我们无需if-then-else语法的代码块就能工作。要么是一个可以让我们直接做对事情的上下文,要么就是在那个上下文之外强迫我们重建它以做对事情。通过可变的实现的细心使用,可以得到产生更少的并且更易读的代码。这可以通过一些代码来说明,比如下面的(不是实际的)购物车的代码:
public class ShoppingCart {
private ArrayList<Item> cart = new ArrayList<Item>();
public void add(Item item) { cart.add(item); }
public Item takeNext() { return cart.remove(0); }
public boolean isEmpty() { return cart.isEmpty(); }
}
假定我们的网店提供可以下载的和需要寄送的商品。构建另一个对象来支持这些操作:public class Shipping {
public boolean ship(Item item, SurfaceAddress address) { ... }
public boolean ship(Item item, EMailAddress address { ... }
}
当顾客结完帐时需要寄送的商品:
while (!cart.isEmpty()) {
shipping.ship(cart.takeNext(), ???);
}
???参数不是什么新奇的操作符,它是在问应该发电子邮件寄送还是用普通的邮寄呢?回答这个问题的上下文还不存在。我们可以将寄送方法表示成一个boolean或者enum,然后使用一个if-then-else来填充缺失的参数。另一种解决方法是创建两个基于Item的类,假定是DownloadableItem和SurfaceItem。现在再写一些代码。我将Item作为一个Interface,支持一个方法,ship。为了寄送购物车中的货物,调用item.ship(shipper)。DownloadableItem和SurfaceItem都会实现ship。public class DownloadableItem implements Item {
public boolean ship(Shipping shipper) {
shipper.ship(this, customer.getEmailAddress());
}
}
public class SurfaceItem implements Item {
public boolean ship(Shipping shipper) {
shipper.ship(this, customer.getSurfaceAddress());
}
}
在这个例子中,我们Shipping工作的责任委托给了每个Item。既然每个Item知道自己该如何寄送,这样我们就不再需要if-then-else来完成了。这段代码也展示了两个经常能在一起工作得很好的模式:命令和双重分派。对这些模式的高效使用依赖于多态的细心使用;那样我们代码中的if-then-else代码块就会少很多。有很多使用if-then-else比使用多态更可行的情况,但更多的是使用多态的风格会得到更小、更易读和更牢靠的代码。错过的机会的数量是代码中if-then-else语句的数量和。
原文:Missing Opportunities for Polymorphism by Kirk Pepperdine