北川广海の梦

北川广海の梦

设计模式:代理模式与迭代器模式

2021-11-04

代理模式

代理模式可以让我们建立一个与被代理对象实现了相同功能接口的代理对象。并且代理对象能够适用于任何依赖原被代理对象的场景。

通过代理模式,我们能对客户端的请求进行拦截,例如对参数进行校验,对原返回值进行处理,甚至改变传入的参数,增加业务逻辑。

由此可以看出,代理模式是对原对象(非原功能)的一种加强。它可以增强对原对象的访问控制。

和其他模式的差异
外观模式与代理模式很相似,但是外观模式的外观对象和原对象的接口并不相同,外观模式实现的是一个新的,易于客户端当前场景使用的接口。

装饰模式往往是为了对对象功能进行增强,即增加原对象的功能,在客户端需要扩展功能时,客户端会主动来创建装饰对象。而代理模式是对对象加强控制,加强控制的手段可以是参数的校验、修改,返回值的校验、修改,甚至是操作日志的记录。并且代理对象可以自行管理被代理对象的生命周期,例如延时创建等。

适配器模式是为了使一个实现了接口A的对象能够在需要实现了接口B的对象场景中发挥作用。通过适配器,让特定场景忽略接口定义上的差异,从对象功能本身的角度,进行满足。

迭代器模式

当我们面临的集合是一个较为复杂的数据结构时,它的遍历代码也可能非常复杂臃肿。

而使用迭代器,可以有效的提供一个针对集合的抽象对象,当客户端需要遍历的时候,无需再自行实现各种复杂的逻辑,不需再纠结选择for循环遍历还是递归遍历。只需不断地Move,然后拿取Current即可。

 public class BinaryTreeNode<T> : IEnumerable<BinaryTreeNode<T>>
        {
            private IEnumerator<BinaryTreeNode<T>> enumerator;
            public BinaryTreeNode(T value)
            {
                Value = value;
                enumerator = new BinaryTreeEnumator(this);
            }
            public BinaryTreeNode<T> Left { get; set; }
            public BinaryTreeNode<T> Right { get; set; }
            public T Value { get; }

            public IEnumerator<BinaryTreeNode<T>> GetEnumerator()
            {
                return enumerator;
            }

            IEnumerator IEnumerable.GetEnumerator()
            {
                return enumerator;
            }
            private class BinaryTreeEnumator : IEnumerator<BinaryTreeNode<T>>
            {
                public BinaryTreeNode<T> Current { get; private set; }

                private BinaryTreeNode<T> _current;
                private readonly BinaryTreeNode<T> _root;

                private readonly Stack<BinaryTreeNode<T>> stack = new Stack<BinaryTreeNode<T>>();
                object IEnumerator.Current { get; }

                public BinaryTreeEnumator(BinaryTreeNode<T> current)
                {
                    Current = current;
                    _current = current;
                    _root = current;
                }
                public void Dispose()
                {
                    stack.Clear();
                }

                public bool MoveNext()
                {
                    if (_current == null && !stack.Any())
                    {
                        return false;
                    }
                    while (_current != null)
                    {
                        stack.Push(_current);
                        _current = _current.Left;
                    }
                    _current = stack.Pop();
                    Current = _current;
                    _current = Current.Right;

                    return true;
                }

                public void Reset()
                {
                    stack.Clear();
                    Current = _root;
                    _current = _root;
                }
            }
        }


        static void Main(string[] args)
        {
            var root = new BinaryTreeNode<int>(1);
            root.Left = new BinaryTreeNode<int>(0);
            root.Right = new BinaryTreeNode<int>(2);

            var enumerator = root.GetEnumerator();
            while (enumerator.MoveNext())
            {
                Console.WriteLine(enumerator.Current.Value);
            }
        }

在C#语言中,针对所有的集合类都实现了迭代器,我们都可以通过foreach去遍历。