OO中的hook到底是什么

2018-10-22  本文已影响0人  kid551

在面向对象的设计中,会遇到很多代码库写到hook(钩子)这个东西。对新手来讲,明白hook是什么很重要,它意味着更加精细的“隔离”设计,而不是粗放地直接做继承。

在Thinking in Java中,谈到Iterator的时候提出了一个问题:如果某个方法需要去一个个地处理一堆元素,直接继承Collection和还是实现Iterator好用一点呢?

直观来看,直接继承Collection是一个方便的选择。

class InterfaceVsIterator {
    public static void display(Iterator<Pet> it) {
        while (it.hasNext()) {
            Pet p = it.next();
            System.out.println(p.id() + ":" + p + " ");
        }
    }
    
    public static void display(Collection<Pet> pets) {
        for (Pet pet : pets) {
            System.out.println(p.id() + ":" + p + " ");
        }
        System.out.println();
    }
}

这里的InterfaceVsIterator其实是一个消费者,专门消费提供的Collection或者Iterator。那么,消费哪一种东西会让你的代码变得更加灵活呢?

如果是直接继承AbstractCollection则需要实现size()iterator()方法,例如:

class CollectionSequence extends AbstractCollection<Pet> {
    
    private Pet[] pets = Pets.createArray(8);

    @Override
    public Iterator<Pet> iterator() {
        return new Iterator<Pet>() {
            private int index = 0;
            
            public boolean hasNext() {
                return index < pets.length;
            }

            public Pet next() {
                return pets[index++];
            }
            
        };
    }

    @Override
    public int size() {
        return pets.length;
    }
    
}

不仅是要实现display()用不到的size()方法,并且同时需要提供Iterator的一个实例。

另一方面,Java的语法是不支持多重继承的。所以,如果你的类已经继承了某个别的不同于AbstractCollection的类,则它就无法再去继承AbstractCollection了。而接口则是可以实现多个。

class PetSequence {
    protected Pet[] pets = new Pet[] {new Pet(), new Pet()};
}

public class NonCollectionSequence extends PetSequence {
    
    public Iterator<Pet> iterator() {
        return new Iterator<Pet>() {
            private int index = 0;
            public boolean hasNext() {
                return index < pets.length;
            }

            public Pet next() {
                return pets[index++];
            }
            
        };
    }
    
    public static void main(String[] args) {
        NonCollectionSequence nc = new NonCollectionSequence();
        InterfaceVsIterator.display(nc.iterator());
    }
}

使用Iterator有更多的灵活性,本质上它体现了Interface在Java中的灵活性。Interface可以将真正被使用于business logic的部分最小化,不必实现非业务的多余部分。另一方面,由于可以实现多个Interface,它可以为已有的组件提供更多的功能。

这里,这个被复用的部分就是hook。

总结起来,Interface更像是一个强制实现某个方法的工具。有了它,就可以在语法层级强制实现某个方法,从而保证了hook上达成一致。

上一篇下一篇

猜你喜欢

热点阅读