C# 设计模式-迭代器模式

迭代器模式-提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的结构

每一种数据结构(包括自定义)遍历自身内部的数据方式都是不同的。

但是我们又希望和常规的遍历方式一样调用,就如for和foreach一样遍历。

想要以相同的方式遍历不同类型的聚合对象,首先就要有一个相同的接口方法来统一获取,我们可以自定义,也可以使用C#自带的IEnumerable。注意:只有继承于IEnumerable的接口才能使用foreach。否则只能使用for或者while来遍历。

能够遍历一个聚合对象的数据主要看2点,是否存在值,以及取出该值。那么由此,就可以再次定义一个接口实现上述的2点。我们仍然可以自定义或者采用C#自带的IEnumerator

定义一个聚合类继承于IEnumerable,实现GetEnumerator()方法。定义一个迭代器类继承于IEnumerator,在这个迭代器中实现真正迭代的逻辑。在GetEnumerator中返回这个迭代器。最后使用foreach去直接遍历这个聚合类或者使用for或者while去处理IEnumerator。


下面用代码来说明:

先采用自定义的方式

1.根据上述说明,我们需要在聚合类中统一接口来获取一个统一的迭代器

定义迭代器接口

public interface IAnimalIterator
    {
        //是否存在下一项的值
        bool HasNext();
        //下一项的值
        object Next();
    }

定义获取方法接口

    public interface IAnimal
    {
        IAnimalIterator GetAnimals();
    }

2.定义聚合类,并继承于IAnimal

    public class Duck:IAnimal
    {
        private static int MAX = 7;
        //可以采用其他实体类型
        private string[] Names = new string[MAX];

        public Duck()
        {
            Names[0] = "第零只鸭子";
            Names[1] = "第一只鸭子";
            Names[2] = "第二只鸭子";
            Names[3] = "第三只鸭子";
            Names[4] = "第四只鸭子";
            Names[5] = "第五只鸭子";
            Names[6] = "第六只鸭子";
        }
        //实现接口
        public IAnimalIterator GetAnimals()
        {
            return new DuckIterator(Names);
        }
    }

3.定义迭代器类,继承迭代器接口

    public class DuckIterator:IAnimalIterator
    {
        private readonly string[] _name;
        int _position = 0;

        public DuckIterator(string[] name)
        {
            _name = name;
        }

        public bool HasNext()
        {
            if (_position >= _name.Length || _name[_position] == null)
                return false;
            return true;
        }

        public object Next()
        {
            string name = _name[_position];
            _position++;
            return name;
        }
    }

4.调用,遍历Duck中的Name

Duck duck = new Duck();
var iterator = duck.GetAnimals();
while (iterator.HasNext())
{
    Console.WriteLine((string)iterator.Next());
}

5.新建一个聚合类

    public class Duck:IAnimal
    {
        private static int MAX = 7;
        private string[] Names = new string[MAX];

        public Duck()
        {
            Names[0] = "第零只鸭子";
            Names[1] = "第一只鸭子";
            Names[2] = "第二只鸭子";
            Names[3] = "第三只鸭子";
            Names[4] = "第四只鸭子";
            Names[5] = "第五只鸭子";
            Names[6] = "第六只鸭子";
        }

        public IAnimalIterator GetAnimals()
        {
            return new DuckIterator(Names);
        }
    }

6.为新建的Chicken类添加一个迭代器

     public class ChickenIterator:IAnimalIterator
    {
        private readonly List<string> _name;
        private int _position = 0;

        public ChickenIterator(List<string> name)
        {
            _name = name;
        }

        public bool HasNext()
        {
            //和duck几乎一样,只是count和length的区别
            if (_position >= _name.Count || _name[_position] == null)
                return false;
            return true;
        }

        public object Next()
        {
            string name = _name[_position];
            _position++;
            return name;
        }
    }

7.调用

Chicken chicken = new Chicken();
var chickenIterator = chicken.GetAnimals();
while (chickenIterator.HasNext())
{
    Console.WriteLine((string)chickenIterator.Next());
}

和Duck的调用也几乎一样,可封装一下方法

8.

        static void Main(string[] args)
        {
            Duck duck = new Duck();
            var duckIterator = duck.GetAnimals();
            Get(duckIterator);

            Chicken chicken = new Chicken();
            var chickenIterator = chicken.GetAnimals();
            Get(chickenIterator);

            Console.ReadLine();
        }

        static void Get(IAnimalIterator iterator)
        {
            while (iterator.HasNext())
            {
                Console.WriteLine((string)iterator.Next());
            }
        }

上面讲了自定义迭代器,实际上C#已经实现了迭代器,就是IEnumerable和IEnumerator

下面将自定义的迭代器换成C#

1.聚合类

Duck

    public class Duck:IEnumerable
    {
        private static int MAX = 7;
        private string[] Names = new string[MAX];

        public Duck()
        {
            Names[0] = "第零只鸭子";
            Names[1] = "第一只鸭子";
            Names[2] = "第二只鸭子";
            Names[3] = "第三只鸭子";
            Names[4] = "第四只鸭子";
            Names[5] = "第五只鸭子";
            Names[6] = "第六只鸭子";
        }

//        public IAnimalIterator GetAnimals()
//        {
//            return new DuckIterator(Names);
//        }

        public IEnumerator GetEnumerator()
        {
            return new DuckIterator(Names);
        }
    }

Chicken

    public class Chicken:IEnumerable
    {
        private List<string> Names;

        public Chicken()
        {
            Names = new List<string>();
            Names.Add("第0只鸡");
            Names.Add("第1只鸡");
            Names.Add("第2只鸡");
            Names.Add("第3只鸡");
            Names.Add("第4只鸡");
        }

//        public IAnimalIterator GetAnimals()
//        {
//            return new ChickenIterator(Names);
//        }

        public IEnumerator GetEnumerator()
        {
            return new ChickenIterator(Names);
        }
    }

2.迭代器类

DuckIterator

    public class DuckIterator:IEnumerator
    {
        private readonly string[] _name;
        int _position = 0;

        public DuckIterator(string[] name)
        {
            _name = name;
        }

//        public bool HasNext()
//        {
//            if (_position >= _name.Length || _name[_position] == null)
//                return false;
//            return true;
//        }
//
//        public object Next()
//        {
//            string name = _name[_position];
//            _position++;
//            return name;
//        }

        public bool MoveNext()
        {
            if (_position >= _name.Length || _name[_position] == null)
                return false;
            return true;
        }

        public void Reset()
        {
            _position = 0;
        }

        public object Current
        {
            get
            {
                string name = _name[_position];
                _position++;
                return name;
            }
        }
    }

ChickenIterator

public class ChickenIterator:IEnumerator
    {
        private readonly List<string> _name;
        private int _position = 0;

        public ChickenIterator(List<string> name)
        {
            _name = name;
        }

//        public bool HasNext()
//        {
//            if (_position >= _name.Count || _name[_position] == null)
//                return false;
//            return true;
//        }
//
//        public object Next()
//        {
//            string name = _name[_position];
//            _position++;
//            return name;
//        }

        public bool MoveNext()
        {
            if (_position >= _name.Count || _name[_position] == null)
                return false;
            return true;
        }

        public void Reset()
        {
            _position = 0;
        }

        public object Current
        {
            get
            {
                string name = _name[_position];
                _position++;
                return name;
            }
        }
    }

调用

    class Program
    {
        static void Main(string[] args)
        {
            Duck duck = new Duck();
            var duckIterator = duck.GetEnumerator();
            Get(duckIterator);

            Chicken chicken = new Chicken();
            var chickenIterator = chicken.GetEnumerator();
            Get(chickenIterator);

            Console.ReadLine();
        }

        static void Get(IEnumerator iterator)
        {
            while (iterator.MoveNext())
            {
                Console.WriteLine((string)iterator.Current);
            }
        }
    }

当然,如果需要迭代的类型已经是迭代类型,我们直接返回这个这个类型的迭代器就可以了,不需要自己去实现一个迭代器

public IEnumerator GetEnumerator()
{
    //return new ChickenIterator(Names);
    //不需要去自定义一个迭代器了,因为List本来就继承于迭代器
    return Names.GetEnumerator();
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值