本文的概念来自深入浅出设计模式一书

项目需求

有两个饭店合并了, 它们各自有自己的菜单. 饭店合并之后要保留这两份菜单.

这两个菜单是这样的:

菜单项MenuItem的代码是这样的:

最初我们是这样设计的, 这是第一份菜单:

这是第2份菜单:

同时有两个菜单存在的问题

问题就是多个菜单把事情变复杂了. 例如: 如果一个服务员需要使用两份菜单的话, 那么她就无法很快的告诉客户有哪些菜是适合素食主义者的了.

服务员还有可能有这些需求:

打印菜单, 打印早餐菜单, 打印午餐菜单, 打印素食菜单, 判断某个菜是否是素食的.

首先我们尝试一下如何实现打印菜单:

1. 调用两个菜单上面的getMenuItem()方法来获取各自的菜单项, 由于它们的菜单不同, 所以需要写两段代码:

2. 打印两个菜单的菜单项, 同样也是两套代码:

3. 如果还有一份菜单, 那么就需要写三套代码....

现在就很麻烦了.

怎么解决这个问题

如果能找到一种方式让这两个菜单同时实现一个接口就好了. 我们已经知道, 要把变化的部分封装起来.

什么是变化的部分? 由于不同对象集合引起的遍历操作.

那我们试试;

1. 想要遍历早餐项, 我们使用ArrayList的size()和get()方法:

2. 想要遍历午餐项, 我们需要使用Array的length成员变量以及通过索引访问数组:

3. 如果我们创建一个对象, 把它叫做迭代器, 让它来封装我们遍历集合的方式怎么样?

这里, 我们需要早餐菜单创建一个迭代器, 如果还有剩余的菜单项没有遍历完, 就获取下一个菜单项.

4. 让我们在Array上试试:

初识迭代器模式

首先你需要知道这种模式依赖于一个迭代器接口. 例如这个:

hasNext()方法告诉我们集合中是否还有剩余的条目没有遍历到.

next()方法返回下一个条目.

有了这个接口, 我们可以在任何一种集合上实现该接口.:

修改代码

定义迭代器接口:

然后再DinerMenu上实现迭代器接口:

然后使用迭代器来修改DinerMenu菜单:

注意: 不要直接返回集合, 因为这样会暴露内部实现.

createIterator()方法返回的是迭代器的接口, 客户并不需要知道DinerMenu是如何维护菜单项的, 也不需要DinerMenu的迭代器是如何实现的. 它只是用迭代器来遍历菜单里面的条目.

最后服务员的代码如下:

测试代码:

我们做了哪些修改?

我们只是为菜单添加了createIterator()方法.

而现在, 菜单的实现被封装了, 服务员不知道菜单是如何保存菜单项的.

我们所需要的只是一个循环, 它可以多态的处理实现了迭代器接口的集合.

而服务员使用的是迭代器接口.

现在呢, 菜单还没有共同的接口, 这意味着服务员仍然被绑定在两个具体的菜单类上, 一会我们再说这个.

当前的设计图

目前就是两个菜单实现了同一套方法, 但是还没有实现同一个接口.

使用C#, .NET Core控制台项目进行实现

菜单项 MenuItem:

  1. namespace IteratorPattern.Menus
  2. {
  3. public class MenuItem
  4. {
  5. public string Name { get; }
  6. public string Description { get; }
  7. public bool Vegetarian { get; }
  8. public double Price { get; }
  9.  
  10. public MenuItem(string name, string description, bool vegetarian, double price)
  11. {
  12. Name = name;
  13. Description = description;
  14. Vegetarian = vegetarian;
  15. Price = price;
  16. }
  17. }
  18. }

迭代器接口 IMyIterator:

  1. namespace IteratorPattern.Abstractions
  2. {
  3. public interface IMyIterator
  4. {
  5. bool HasNext();
  6. object Next();
  7. }
  8. }

两个菜单迭代器:

  1. using IteratorPattern.Abstractions;
  2. using IteratorPattern.Menus;
  3.  
  4. namespace IteratorPattern.MenuIterators
  5. {
  6. public class MyDinerMenuIterator: IMyIterator
  7. {
  8. private readonly MenuItem[] _menuItems;
  9. private int _position;
  10.  
  11. public MyDinerMenuIterator(MenuItem[] menuItems)
  12. {
  13. _menuItems = menuItems;
  14. }
  15.  
  16. public bool HasNext()
  17. {
  18. if (_position >= _menuItems.Length || _menuItems[_position] == null)
  19. {
  20. return false;
  21. }
  22. return true;
  23. }
  24.  
  25. public object Next()
  26. {
  27. var menuItem = _menuItems[_position];
  28. _position++;
  29. return menuItem;
  30. }
  31. }
  32. }
  33.  
  34. using System.Collections;
  35. using IteratorPattern.Abstractions;
  36.  
  37. namespace IteratorPattern.MenuIterators
  38. {
  39. public class MyPancakeHouseMenuIterator:IMyIterator
  40. {
  41. private readonly ArrayList _menuItems;
  42. private int _position;
  43.  
  44. public MyPancakeHouseMenuIterator(ArrayList menuItems)
  45. {
  46. _menuItems = menuItems;
  47. }
  48.  
  49. public bool HasNext()
  50. {
  51. if (_position >= _menuItems.Count || _menuItems[_position] == null)
  52. {
  53. return false;
  54. }
  55. _position++;
  56. return true;
  57. }
  58.  
  59. public object Next()
  60. {
  61. var menuItem = _menuItems[_position];
  62. _position++;
  63. return menuItem;
  64. }
  65. }
  66. }

两个菜单:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using IteratorPattern.Abstractions;
  5. using IteratorPattern.MenuIterators;
  6.  
  7. namespace IteratorPattern.Menus
  8. {
  9. public class MyDinerMenu
  10. {
  11. private const int MaxItems = ;
  12. private int _numberOfItems = ;
  13. private MenuItem[] MenuItems { get; }
  14.  
  15. public MyDinerMenu()
  16. {
  17. MenuItems = new MenuItem[MaxItems];
  18. AddItem("Vegetarian BLT", "(Fakin’) Bacon with lettuce & tomato on whole wheat", true, 2.99);
  19. AddItem("BLT", "Bacon with lettuce & tomato on whole wheat", false, 2.99);
  20. AddItem("Soup of the day", "Soup of the day, with a side of potato salad", false, 3.29);
  21. AddItem("Hotdog", "A hot dog, with saurkraut, relish, onions, topped with cheese", false, 3.05);
  22. }
  23.  
  24. public void AddItem(string name, string description, bool vegetarian, double price)
  25. {
  26. var menuItem = new MenuItem(name, description, vegetarian, price);
  27. if (_numberOfItems >= MaxItems)
  28. {
  29. Console.WriteLine("Sorry, menu is full! Can't add item to menu");
  30. }
  31. else
  32. {
  33. MenuItems[_numberOfItems] = menuItem;
  34. _numberOfItems++;
  35. }
  36. }
  37.  
  38. public IMyIterator CreateIterator()
  39. {
  40. return new MyDinerMenuIterator(MenuItems);
  41. }
  42. }
  43. }
  44.  
  45. using System.Collections;
  46. using IteratorPattern.Abstractions;
  47. using IteratorPattern.MenuIterators;
  48.  
  49. namespace IteratorPattern.Menus
  50. {
  51. public class MyPancakeHouseMenu
  52. {
  53. public ArrayList MenuItems { get; }
  54.  
  55. public MyPancakeHouseMenu()
  56. {
  57. MenuItems = new ArrayList();
  58. AddItem("K&B’s Pancake Breakfast", "Pancakes with scrambled eggs, and toast", true, 2.99);
  59. AddItem("Regular Pancake Breakfast", "Pancakes with fried eggs, sausage", false, 2.99);
  60. AddItem("Blueberry Pancakes", "Pancakes made with fresh blueberries", true, 3.49);
  61. AddItem("Waffles", "Waffles, with your choice of blueberries or strawberries", true, 3.59);
  62. }
  63.  
  64. public void AddItem(string name, string description, bool vegetarian, double price)
  65. {
  66. var menuItem = new MenuItem(name, description, vegetarian, price);
  67. MenuItems.Add(menuItem);
  68. }
  69.  
  70. public IMyIterator CreateIterator()
  71. {
  72. return new MyPancakeHouseMenuIterator(MenuItems);
  73. }
  74. }
  75. }

服务员 Waitress:

  1. using System;
  2. using IteratorPattern.Abstractions;
  3. using IteratorPattern.Menus;
  4.  
  5. namespace IteratorPattern.Waitresses
  6. {
  7. public class MyWaitress
  8. {
  9. private readonly MyPancakeHouseMenu _pancakeHouseMenu;
  10. private readonly MyDinerMenu _dinerMenu;
  11.  
  12. public MyWaitress(MyPancakeHouseMenu pancakeHouseMenu, MyDinerMenu dinerMenu)
  13. {
  14. _pancakeHouseMenu = pancakeHouseMenu;
  15. _dinerMenu = dinerMenu;
  16. }
  17.  
  18. public void PrintMenu()
  19. {
  20. var pancakeIterator = _pancakeHouseMenu.CreateIterator();
  21. var dinerIterator = _dinerMenu.CreateIterator();
  22. Console.WriteLine("MENU\n--------------\nBREAKFIRST");
  23. PrintMenu(pancakeIterator);
  24. Console.WriteLine("\nLUNCH");
  25. PrintMenu(dinerIterator);
  26. }
  27.  
  28. private void PrintMenu(IMyIterator iterator)
  29. {
  30. while (iterator.HasNext())
  31. {
  32. var menuItem = iterator.Next() as MenuItem;
  33. Console.Write($"{menuItem?.Name}, ");
  34. Console.Write($"{menuItem?.Price} -- ");
  35. Console.WriteLine($"{menuItem?.Description}");
  36. }
  37. }
  38. }
  39. }

测试:

  1. static void MenuTestDriveUsingMyIterator()
  2. {
  3. var pancakeHouseMenu = new MyPancakeHouseMenu();
  4. var dinerMenu = new MyDinerMenu();
  5.  
  6. var waitress = new MyWaitress(pancakeHouseMenu, dinerMenu);
  7. waitress.PrintMenu();
  8. }

做一些改进

Java里面内置了Iterator接口, 我们刚才是手写了一个Iterator迭代器接口. Java内置的定义如下:

注意里面这个remove()方法, 我们可能不需要它.

remove()方法是可选实现的, 如果你不想让集合有此功能的话, 就应该抛出NotSupportedException(C#的).

使用java内置的Iterator来实现

由于PancakeHouseMenu使用的是ArrayList, 而ArrayList已经实现了该接口, 那么:这样简单改一下就可以:

针对DinerMe菜单, 还是需要手动实现的:

最后别忘了给菜单规定一个统一的接口:

服务员Waitress类里面也使用Menu来代替具体的菜单, 这样也减少了服务员对具体类的依赖(针对接口编程, 而不是具体的实现):

最后看下改进后的设计类图:

迭代器模式定义

迭代器模式提供了一种访问聚合对象(例如集合)元素的方式, 而且又不暴露该对象的内部表示.

迭代器模式负责遍历该对象的元素, 该项工作由迭代器负责而不是由聚合对象(集合)负责.

类图:

其它问题

  • 迭代器分内部迭代器和外部迭代器, 我们上面实现的是外部迭代器. 也就是说客户控制着迭代, 它通过调用next()方法来获取下个元素. 而内部迭代器由迭代器本身自己控制迭代, 这种情况下, 你需要告诉迭代器遍历的时候需要做哪些动作, 所以你得找到一种方式把操作传递进去. 内部迭代器还是不如外部的灵活, 但是也许使用起来会简单一些?
  • 迭代器意味着无序. 它所遍历的集合的顺序是根据集合来定的, 也有可能会遍历出来的元素值会重复.

单一职责设计原则

一个类应该只有一个变化发生的原因.

写代码的时候这个原则很容易被忽略掉, 只能通过多检查设计来避免违反原则.

所谓的高内聚, 就是只这个类是围绕一套关连的函数而设计的.

而低内聚就是只这个类是围绕一些不相关的函数而设计的.

遵循该原则的类通常是高内聚的, 并且可维护性要比那些多重职责或低内聚的类好.

需求变更

还需要添加另一份菜单:

这个菜单使用的是HashTable.

首先修改该菜单, 让它实现Menu接口:

注意看HashTable的不同之处:

首先通过values()方法获取HashTable的集合对象, 这个对象正好实现了Iterator接口, 直接调用iterator()方法即可.

最后修改服务员类:

测试:

到目前我们做了什么

我们给了服务员一种简单的方式来遍历菜单项, 不同的菜单实现了同一个迭代器接口, 服务员不需要知道菜单项的实现方法.

我们把服务员和菜单的实现解耦了

而且使服务员可以扩展:

还有个问题

现在有三个菜单, 每次再添加一个菜单的时候, 你都得相应的添加一套代码, 这违反了"对修改关闭, 对扩展开放原则".

那我们把这些菜单放到可迭代的集合即可:

C#, .NET Core控制带项目实现

菜单接口:

  1. using System.Collections;
  2.  
  3. namespace IteratorPattern.Abstractions
  4. {
  5. public interface IMenu
  6. {
  7. IEnumerator CreateIEnumerator();
  8. }
  9. }

三个菜单:

  1. using System;
  2. using System.Collections;
  3. using IteratorPattern.Abstractions;
  4. using IteratorPattern.MenuIterators;
  5.  
  6. namespace IteratorPattern.Menus
  7. {
  8. public class DinerMenu: IMenu
  9. {
  10. private const int MaxItems = ;
  11. private int _numberOfItems = ;
  12. private MenuItem[] MenuItems { get; }
  13.  
  14. public DinerMenu()
  15. {
  16. MenuItems = new MenuItem[MaxItems];
  17. AddItem("Vegetarian BLT", "(Fakin’) Bacon with lettuce & tomato on whole wheat", true, 2.99);
  18. AddItem("BLT", "Bacon with lettuce & tomato on whole wheat", false, 2.99);
  19. AddItem("Soup of the day", "Soup of the day, with a side of potato salad", false, 3.29);
  20. AddItem("Hotdog", "A hot dog, with saurkraut, relish, onions, topped with cheese", false, 3.05);
  21. }
  22.  
  23. public void AddItem(string name, string description, bool vegetarian, double price)
  24. {
  25. var menuItem = new MenuItem(name, description, vegetarian, price);
  26. if (_numberOfItems >= MaxItems)
  27. {
  28. Console.WriteLine("Sorry, menu is full! Can't add item to menu");
  29. }
  30. else
  31. {
  32. MenuItems[_numberOfItems] = menuItem;
  33. _numberOfItems++;
  34. }
  35. }
  36.  
  37. public IEnumerator CreateIEnumerator()
  38. {
  39. return new DinerMenuIterator(MenuItems);
  40. }
  41. }
  42. }
  43.  
  44. using System.Collections;
  45. using IteratorPattern.Abstractions;
  46. using IteratorPattern.MenuIterators;
  47.  
  48. namespace IteratorPattern.Menus
  49. {
  50. public class PancakeHouseMenu: IMenu
  51. {
  52. public ArrayList MenuItems { get; }
  53.  
  54. public PancakeHouseMenu()
  55. {
  56. MenuItems = new ArrayList();
  57. AddItem("K&B’s Pancake Breakfast", "Pancakes with scrambled eggs, and toast", true, 2.99);
  58. AddItem("Regular Pancake Breakfast", "Pancakes with fried eggs, sausage", false, 2.99);
  59. AddItem("Blueberry Pancakes", "Pancakes made with fresh blueberries", true, 3.49);
  60. AddItem("Waffles", "Waffles, with your choice of blueberries or strawberries", true, 3.59);
  61. }
  62.  
  63. public void AddItem(string name, string description, bool vegetarian, double price)
  64. {
  65. var menuItem = new MenuItem(name, description, vegetarian, price);
  66. MenuItems.Add(menuItem);
  67. }
  68.  
  69. public IEnumerator CreateIEnumerator()
  70. {
  71. return new PancakeHouseMenuIterator(MenuItems);
  72. }
  73. }
  74. }
  75.  
  76. using System.Collections;
  77. using IteratorPattern.Abstractions;
  78.  
  79. namespace IteratorPattern.Menus
  80. {
  81. public class CafeMenu : IMenu
  82. {
  83. public Hashtable MenuItems { get; } = new Hashtable();
  84.  
  85. public CafeMenu()
  86. {
  87. AddItem("Veggie Burger and Air Fries", "Veggie burger on a whole wheat bun, lettuce, tomato, and fries", true, 3.99);
  88. AddItem("Soup of the day", "A cup of the soup of the day, with a side salad", false, 3.69);
  89. AddItem("Burrito", "A large burrito, with whole pinto beans, salsa, guacamole", true, 4.29);
  90. }
  91.  
  92. public IEnumerator CreateIEnumerator()
  93. {
  94. return MenuItems.GetEnumerator();
  95. }
  96.  
  97. public void AddItem(string name, string description, bool vegetarian, double price)
  98. {
  99. var menuItem = new MenuItem(name, description, vegetarian, price);
  100. MenuItems.Add(menuItem.Name, menuItem);
  101. }
  102.  
  103. }
  104. }

菜单的迭代器:

  1. using System;
  2. using System.Collections;
  3. using IteratorPattern.Menus;
  4.  
  5. namespace IteratorPattern.MenuIterators
  6. {
  7. public class DinerMenuIterator: IEnumerator
  8. {
  9. private readonly MenuItem[] _menuItems;
  10. private int _position = -;
  11.  
  12. public DinerMenuIterator(MenuItem[] menuItems)
  13. {
  14. _menuItems = menuItems;
  15. }
  16.  
  17. public bool MoveNext()
  18. {
  19. _position++;
  20. if (_position >= _menuItems.Length || _menuItems[_position] == null)
  21. {
  22. return false;
  23. }
  24. return true;
  25. }
  26.  
  27. public void Reset()
  28. {
  29. _position = -;
  30. }
  31.  
  32. public object Current => _menuItems[_position];
  33. }
  34. }
  1. using System.Collections;
  2. using System.Collections.Generic;
  3.  
  4. namespace IteratorPattern.MenuIterators
  5. {
  6. public class PancakeHouseMenuIterator : IEnumerator
  7. {
  8. private readonly ArrayList _menuItems;
  9. private int _position = -;
  10.  
  11. public PancakeHouseMenuIterator(ArrayList menuItems)
  12. {
  13. _menuItems = menuItems;
  14. }
  15.  
  16. public bool MoveNext()
  17. {
  18. _position++;
  19. if (_position >= _menuItems.Count || _menuItems[_position] == null)
  20. {
  21. return false;
  22. }
  23. return true;
  24. }
  25.  
  26. public void Reset()
  27. {
  28. _position = -;
  29. }
  30.  
  31. public object Current => _menuItems[_position];
  32. }
  33. }

服务员:

  1. using System;
  2. using System.Collections;
  3. using IteratorPattern.Abstractions;
  4. using IteratorPattern.Menus;
  5.  
  6. namespace IteratorPattern.Waitresses
  7. {
  8. public class Waitress
  9. {
  10. private readonly ArrayList _menus;
  11.  
  12. public Waitress(ArrayList menus)
  13. {
  14. _menus = menus;
  15. }
  16.  
  17. public void PrintMenu()
  18. {
  19. var menuIterator = _menus.GetEnumerator();
  20. while (menuIterator.MoveNext())
  21. {
  22. var menu = menuIterator.Current as IMenu;
  23. PrintMenu(menu?.CreateIEnumerator());
  24. }
  25. }
  26.  
  27. private void PrintMenu(IEnumerator iterator)
  28. {
  29. while (iterator.MoveNext())
  30. {
  31. if (iterator.Current != null)
  32. {
  33. MenuItem menuItem;
  34. if (iterator.Current is MenuItem item)
  35. {
  36. menuItem = item;
  37. }
  38. else
  39. {
  40. menuItem = ((DictionaryEntry)iterator.Current).Value as MenuItem;
  41. }
  42. Console.Write($"{menuItem?.Name}, ");
  43. Console.Write($"{menuItem?.Price} -- ");
  44. Console.WriteLine($"{menuItem?.Description}");
  45. }
  46. }
  47. Console.WriteLine();
  48. }
  49. }
  50. }

测试:

  1. static void MenuTestDriveUsingIEnumerator()
  2. {
  3. var pancakeHouseMenu = new PancakeHouseMenu();
  4. var dinerMenu = new DinerMenu();
  5. var cafeMenu = new CafeMenu();
  6.  
  7. var waitress = new Waitress(new ArrayList()
  8. {
  9. pancakeHouseMenu, dinerMenu, cafeMenu
  10. });
  11. waitress.PrintMenu();
  12. }

深入浅出设计模式的C#实现的代码: https://github.com/solenovex/Head-First-Design-Patterns-in-CSharp

这篇先到这, 本章涉及到组合模式, 下篇文章再写.

用C# (.NET Core) 实现迭代器设计模式的更多相关文章

  1. 使用C# (.NET Core) 实现迭代器设计模式 (Iterator Pattern)

    本文的概念来自深入浅出设计模式一书 项目需求 有两个饭店合并了, 它们各自有自己的菜单. 饭店合并之后要保留这两份菜单. 这两个菜单是这样的: 菜单项MenuItem的代码是这样的: 最初我们是这样设 ...

  2. 使用C# (.NET Core) 实现组合设计模式 (Composite Pattern)

    本文的概念性内容来自深入浅出设计模式一书. 本文需结合上一篇文章(使用C# (.NET Core) 实现迭代器设计模式)一起看. 上一篇文章我们研究了多个菜单一起使用的问题. 需求变更 就当我们感觉我 ...

  3. “全栈2019”Java第九十三章:内部类应用场景(迭代器设计模式)

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  4. 使用 C#/.NET Core 实现单体设计模式

    本文的概念内容来自深入浅出设计模式一书 由于我在给公司做内培, 所以最近天天写设计模式的文章.... 单体模式 Singleton 单体模式的目标就是只创建一个实例. 实际中有很多种对象我们可能只需要 ...

  5. 详解 ASP.NET Core MVC 的设计模式

    MVC 是什么?它是如何工作的?我们来解剖它 在本节课中我们要讨论的内容: 什么是 MVC? 它是如何工作的? 什么是 MVC MVC 由三个基本部分组成 - 模型(Model),视图(View)和控 ...

  6. JAVA设计模式之迭代器设计模式

    一.迭代器模式简介 Iterator模式也叫迭代模式,是行为模式之一,它把对容器中包含的内部对象的访问委让给外部类,使用Iterator(遍历)按顺序进行遍历访问的设计模式. 二.迭代器模式的角色与职 ...

  7. 迭代器设计模式,帮你大幅提升Python性能

    大家好,我们的git专题已经更新结束了,所以开始继续给大家写一点设计模式的内容. 今天给大家介绍的设计模式非常简单,叫做iterator,也就是迭代器模式.迭代器是Python语言当中一个非常重要的内 ...

  8. 使用C# (.NET Core) 实现单体设计模式 (Singleton Pattern)

    本文的概念内容来自深入浅出设计模式一书 由于我在给公司做内培, 所以最近天天写设计模式的文章.... 单体模式 Singleton 单体模式的目标就是只创建一个实例. 实际中有很多种对象我们可能只需要 ...

  9. Design Pattern Iterator 迭代器设计模式

    这个设计模式感觉很easy,我们平时敲代码的时候也是常常须要调用iterator的,C++和Java都是. 所以感觉没什么特别的.就是须要模仿C++或者Java的iterator类的功能吧. 这里简单 ...

随机推荐

  1. SQL 数据库连续插入大批量数据时超时

    经常会处理大批量千万级的数据,一直以来都没问题.最近在处理时确出来了经常超时,程序跑一段时间就得停下来重启服务器,根据几次的调整发现了问题的所在,产生这类问题主要是以下几点所导致:      1.数据 ...

  2. js网页判断移动终端浏览器版本信息是安卓还是苹果ios,判断在微信浏览器跳转不同页面,生成二维码

    一个二维码,扫描进入网页,自动识别下载苹果和安卓客户端,判断网页如下,(只有苹果的微信不能自动跳转)所以加个微信判断. <!DOCTYPE html> <html> <h ...

  3. C#,DataHelper,一个通用的帮助类,留个备份。

    using System; using Newtonsoft.Json; using System.IO; using System.Text; namespace CarHailing.Base { ...

  4. Java基础学习笔记十九 IO

    File IO概述 回想之前写过的程序,数据都是在内存中,一旦程序运行结束,这些数据都没有了,等下次再想使用这些数据,可是已经没有了.那怎么办呢?能不能把运算完的数据都保存下来,下次程序启动的时候,再 ...

  5. 十个 PHP 开发者最容易犯的错误

    PHP 语言让 WEB 端程序设计变得简单,这也是它能流行起来的原因.但也是因为它的简单,PHP 也慢慢发展成一个相对复杂的语言,层出不穷的框架,各种语言特性和版本差异都时常让搞的我们头大,不得不浪费 ...

  6. [ZLXOI2015]殉国

    2057. [ZLXOI2015]殉国 http://cogs.pro/cogs/problem/problem.php?pid=2057 ★☆   输入文件:BlackHawk.in   输出文件: ...

  7. wpf研究之道——datagrid控件数据绑定

    前台: <DataGrid x:Name="TestCaseDataGrid" ItemsSource="{Binding}" > {binding ...

  8. nyoj 疯牛

    疯牛 时间限制:1000 ms  |  内存限制:65535 KB 难度:4   描述 农夫 John 建造了一座很长的畜栏,它包括N (2 <= N <= 100,000)个隔间,这些小 ...

  9. 《javascript设计模式与开发实践》阅读笔记(15)—— 装饰者模式

    装饰者模式 可以动态地给某个对象添加一些额外的职责,而不会影响从这个类中派生的其他对象.在程序开发中,许多时候都并不希望某个类天生就非常庞大,一次性包含许多职责.那么我们就可以使用装饰者模式. 代码例 ...

  10. 【编程开发】PHP---面向对象

    面向对象编程 类:在现实世界中,任何事物都有种类的概念:车 类是由特征和行为构成的. 特征:都是不动的,从出厂的时候就已经内置好了(属性) 行为:一种动的状态.(方法(函数)) 行为依赖于这些特征,而 ...