博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
设计模式之初:理解面向对象设计
阅读量:5303 次
发布时间:2019-06-14

本文共 3631 字,大约阅读时间需要 12 分钟。

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

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

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("{1}", i, i + 1); 16  } 17 18 return strB.ToString(); 19  } 20 }

WebForm前台调用:

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

打印的样子:

 我们主要关注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("{1}", 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("{1}", 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

你可能感兴趣的文章
[LeetCode] 55. Jump Game_ Medium tag: Dynamic Programming
查看>>
[Cypress] Stub a Post Request for Successful Form Submission with Cypress
查看>>
程序集的混淆及签名
查看>>
判断9X9数组是否是数独的java代码
查看>>
00-自测1. 打印沙漏
查看>>
UNITY在VS中调试
查看>>
SDUTOJ3754_黑白棋(纯模拟)
查看>>
Scala入门(1)Linux下Scala(2.12.1)安装
查看>>
如何改善下面的代码 领导说了很耗资源
查看>>
Quartus II 中常见Warning 原因及解决方法
查看>>
php中的isset和empty的用法区别
查看>>
Android ViewPager 动画效果
查看>>
pip和easy_install使用方式
查看>>
博弈论
查看>>
Redis sentinel & cluster 原理分析
查看>>
我的工作习惯小结
查看>>
把word文档中的所有图片导出
查看>>
浏览器的判断;
查看>>
ubuntu 18.04取消自动锁屏以及设置键盘快捷锁屏
查看>>
Leetcode 589. N-ary Tree Preorder Traversal
查看>>