类和接口 - 包装类

继承固然非常强大,但我们不能滥用继承,如使用不当,则会引起诸多问题.只有当子类和超类之间确实存在"is-a"关系的时候,使用继承才是恰当的.即便如此,如果子类和超类在不同的包中,并且超类不是为了继承而设计的,那么继承将会是脆弱的.此时,我们应该考虑用包装类,一复合和转发机制来代替继承.
让我们来看个具体的例子: 我们假设程序用了个HashSet, 我们想统计一个HashSet对象创建以来总共加了多少个元素,为了实现这个功能,我们首先考虑继承,然后覆盖原有的实现加个计数:
 package com.effective.item16;

import java.util.Collection;
import java.util.HashSet;

public class InstrumentedHashSet<E> extends HashSet<E> {

private static final long serialVersionUID = 1L;

private int count = 0;

InstrumentedHashSet() {
super();
}

@Override
public boolean add(E e){
count++;
return super.add(e);
}

@Override
public boolean addAll(Collection<? extends E> c){
count += c.size();
return super.addAll(c);
}

public int getCount(){
return count;
}

}


结果发现但我们调用如下代码时,计数本应为3,真实结果为6. 什么原因呢? 原来父类HashSet里面addAll方法调用了add方法.这种内部细节,我们作为api的使用者很难知道,除非查看源码. 继而又有个严重的问题,如果HashSet的具体实现改变了,那么又有可能引起其他的问题,很难察觉.
让我们换种思路,采用复合代替继承.

import java.util.Collection;
import java.util.Iterator;
import java.util.Set;

public class WrapperSet<E> implements Set<E> {

private int count = 0;
private Set<E> s;

private WrapperSet(Set<E> s) {
super();
this.s = s;
}

...

@Override
public boolean add(E e) {
count++;
return s.add(e);
}

@Override
public boolean remove(Object o) {
return s.remove(o);
}

@Override
public boolean containsAll(Collection<?> c) {
return c.containsAll(c);
}

@Override
public boolean addAll(Collection<? extends E> c) {
if(c != null)
count += c.size();
return s.addAll(c);
}
...

}


Set接口保存了HashSet的功能特性,看似麻烦了些,但程序变得健壮了,这种Wrapper设计也带来了灵活性,他可以包装任何的Set实现, 同时又很好的扩展了计数器.
关于包装类,大家可以结合Decorator模式和Proxy模式做更深入的研究.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值