设计模式之初:理解面向对象设计

     人言:总结使人进步;为了进一步巩固自己学到的东西和了解新的知识,决定通过博客园来记录自己学习设计模式的过程,本人没有学过设计模式,只是背过一些概念,从现在起,我会通过一个个的例子来让自己学习每个模式并记录下来,有需要的朋友一起来。

   “面向对象”这个字眼,估计你已经熟的透了,然而可能还是无法在实际编程中运用自如,尽管我们都知道“类”、“封装、继承、多态”概念,却依然写着面向过程的代码。举个最简单的例子:分页控件

 1    public partial class WebForm1 : System.Web.UI.Page
 2     {
 3         protected void Page_Load(object sender, EventArgs e)
 4         {
 5 
 6         }
 7 
 8         protected string BuildPager(int pageIndex, int count, int pageSize = 10)
 9         {
10             StringBuilder strB = new StringBuilder();
11             int pageCount = count / pageSize + (count % pageSize == 0 ? 0 : 1);
12 
13             for (int i = 0; i < pageCount; i++)
14             {
15                 strB.AppendFormat("<a href='/webform1.aspx?pindex={0}' >{1}</a>", i, i + 1);
16             }
17 
18             return strB.ToString();
19         }
20     }

WebForm前台调用:

 <div>
       <%=BuildPager(1,100,10) %>
 </div>

打印的样子:

 我们主要关注BuildPager方法,对于以上的代码能实现功能吗?绝对可以,面向对象吗?也算是有一点点,这时可能就会有人问,怎么就算面向对象了,或许你立刻想到三要素“封装继承多态”了,之前听到一位大牛对面向对象的总结:对象的职责问题。个人感觉总结的精辟到了极点。

我们不得不考虑关于BuildPager方法的几个使用情形,来来考量它是否符合。

第一:它是否便于其他类或对象调用;比如还有一个页面B需要分页,B是否能很容易调用这个方法呢?显然能:在B中写:WebForm1 wf = new WebForm1(); wf.BuilderPager(....);就可以了。但是基于刚才提到的“对象的职责问题”再考虑一下,就会发现,“BuildPager"功能并不应该属于WebFomr1这个类,因为WebForm2可能也会有,这是可能有人会想,那就放到基类Page里去,这样所有的子类都有了,好想法,然后忽略了一种不同页面,分页标签不一样的情况(有的用A有的用span),这是可能你会想到那就用Virtual,不同的分页方法就在子类里重写,好办法。这时我们已经运用了继承和多态两个特性。但是还有一种情况,子类的5个页面的分页用A标签,另外10个页面用span标签,这时,我们当然可以通过重写实现。但是会出现大量的重复代码。怎么办呢,运用封装的概念,再新建一个类Pager,把分页的代码放进去。

 1     public class Pager
 2     {
 3         public virtual string BuildPager(int pageIndex, int count, int pageSize = 10)
 4         {
 5             StringBuilder strB = new StringBuilder();
 6             int pageCount = count / pageSize + (count % pageSize == 0 ? 0 : 1);
 7 
 8             for (int i = 0; i < pageCount; i++)
 9             {
10                 strB.AppendFormat("<a href='/webform1.aspx?pindex={0}' >{1}</a>", i, i + 1);
11             }
12 
13             return strB.ToString();
14         }
15     }

对于运用不同标签的方式,我们通过集成和多态来实现。

A标签分页类和Span标签分页类

调用的时候,需要那种方式,就创建那种对象。

1         protected void Page_Load(object sender, EventArgs e)
2         {
3             Pager pager = new PagerUseSpanTag(); // 或者 new PagerUseATag();
4 
5             var pagerHtml = pager.BuildPager(0, 1000, 10);
6         }

这一的话,对于刚才的那个多个页面有相同分页的需求就轻而易举的解决了,现在能很容易的扩展分页的功能了,然而还有一个问题不知你发现了没,就是我们的分页方法的代码,它把分页的逻辑和展现都写到一个函数里了。如果有一天,Leader说分页的逻辑要变,那么你需要重写所有的Pager子类的分页方法了,而且修改的内容多数相同(只修改逻辑)。根据”对象的职责问题“,我们发现,分页的逻辑和分页的展示 对Pager类而言应该是两个独立的功能,Pager类应该这样写:

 1     public class Pager
 2     { 
 3         //逻辑
 4         public virtual string BuildPager(int pageIndex, int count, int pageSize = 10)
 5         {
 6             StringBuilder strB = new StringBuilder();
 7             int pageCount = count / pageSize + (count % pageSize == 0 ? 0 : 1);
 8 
 9             for (int i = 0; i < pageCount; i++)
10             {
11                 strB.AppendFormat(GetUnitPageHtml(i, (i + 1).ToString()));
12             }
13 
14             return strB.ToString();
15         }
16 
17         //展示
18         protected virtual string GetUnitPageHtml(int pageIndex, string pageText)
19         {
20             return string.Format("<a href='/webform1.aspx?pindex={0}' >{1}</a>", pageIndex, pageText);
21         }
22     }

这样的话,如果逻辑变了,在子类中重写”BuildPager“方法,如果展示变了”GetUnitPageHtml"方法,再看他两个子类写法:

新的两个子类

如果 分页标签为A的逻辑变了,那就新加类 BigPagerUseATag,并重写 BuildPager方法即可。

 1     public class BigPagerUseATag : PagerUseATag
 2     {
 3         public override string BuildPager(int pageIndex, int count, int pageSize = 10)
 4         {
 5             StringBuilder strB = new StringBuilder();
 6 
 7             /*
 8              * 你的新的分页逻辑
 9             */
10 
11             return strB.ToString();
12         }
13     }

到目前为止,这个分页基本上能解决大部分的分页遇到的问题了,无论扩展性还是修改时的成本控制,都得到了有效的提升。在这个过程中,我们运用面向对象的理念,封装:把正确的功能放到正确的类中(如果没有类就新建),继承:修改功能尽量不要直接修改代码,通过新增子类的方式实现,多态:不同的功能在不同的子类中有不一样的效果。到此Pager可以称为一个可复用的组件了,可以单独放到某个框架中供多个项目调用了。

设计模式的基础是面向对象,面向对象的基础夯实了,设计模式就是思考解决问题的捷径思路。 

谢谢!

原文地址:https://www.cnblogs.com/wimlh/p/4011043.html