简体   繁体   中英

Java - implement iterator with strategy

I am trying to implement a custom iterator for a composite class and use different strategies in the iterator implementation depending on how the client wants to traverse the composite structure.

public class MyComposite implements Iterable<MyComponent> {

    ArrayList<MyComponent> childComponents;

    //MyComposite methods

    @Override
    public Iterator<MyComponent> iterator() {
        return new MyIterator(this);
    }
}

I would like to pass a MyIteratorStrategy object as part of the iterator construction, however the Iterable interface does not permit passing objects to the iterator method.

public class SomeClient {
    private void traverseComposite() {
        MyComposite myComposite = new MyComposite();

        MyIteratorStrategy fooStrategy = new MyIteratorStrategy("foo");
        MyIteratorStrategy barStrategy = new MyIteratorStrategy("bar");

        MyIterator fooIterator = myComposite.iterator(fooStrategy);
        MyIterator barIterator = myComposite.iterator(barStrategy);     
    }
}

Here's how I'm utilizing the strategy in the iterator implementation:

public class MyIterator implements Iterator<MyComponent> {

    MyComponent component;
    MyIteratorStrategy strategy;

    public MyIterator(MyComponent component, MyIteratorStrategy strategy) {
        this.component = component;
        this.strategy = strategy;
    }

    @Override
    public Component next() {
        if(strategy.isDone(component) {
            //return some child component
        } else {
            //return some other child component
        }
    }

    //rest of implementation
}

I'm trying to learn how to utilize design patterns, so perhaps I'm being overly general. How can I cleanly inject the strategy into the iterator?

Change MyIterator to be the class that implements Iterable<MyComponent> , instead of Iterator . (You might want to rename it something like MyComponentScanner for clarity.)

Move the public Iterator<MyComponent> iterator() method over from the MyComposite class to MyIterator (or whatever you rename it).

Example...

public class MyComponentScanner implements Iterable<MyComponent> {

    MyComponent component;
    MyIteratorStrategy strategy;

    public MyComponentScanner(MyComponent component, MyIteratorStrategy strategy) {
        this.component = component;
        this.strategy = strategy;
    }

    @Override
    public Iterator<MyComponent> iterator() {
        return new Iterator() {
            @Override
            public Component next() {
                if(strategy.isDone(component) {
                    //return some child component
                } else {
                    //return some other child component
                }
            }
        };
    }

    //rest of implementation
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM