从一个网页生成系统看怎么在程序中实现面向对象三大基本特性
我们发现网页虽然有很多类别,但是他们的生成过程基本都是相同的,都有相同的三步:
第一步:读取网页模板。第二步:用数据库内容替换模板标记。第三步:保存生成的网页。
其中第一步读取网页模板时我们把公共部分(头部和尾部)单独做成了一个模板,读取时加了缓存。第二步替换内容时包括替换三个方面的内容:一是替换Seo的内容,二是替换文章内容信息,三是替换广告信息。
既然大家都有相同的生成过程,那么我们就把这个过程抽象出来,写成一个抽象类,在类中用虚方法把他们的主要步骤表示出来 。具体代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EworksCms.Domain;
using EworksCms.Domain.CreatePage;
using EworksCms.BLInterface;
using EworksCms.BL.AdManage;
using Framework.CreatePageHelper;
using CommTool;
namespace Framework._CreatePage
{
public abstract class AbstractEworksCreatePage
{
private EworksCreateTopicConfig _config;//网站栏目配置信息,包括栏目id,模板路径,广告Id、seo信息等
public EworksCreateTopicConfig Config
{
get { return _config; }
set { _config = value; }
}
/// <summary>
/// 获取模版页面内容
/// </summary>
/// <returns></returns>
public virtual string GetPageModelContent()
{
if (Config != null)
{
string modelvirtualfile = Config.ModelPath;//模板虚拟路径
string physicfile = SitePathHelper.GetModelFilePhysicalPath() + modelvirtualfile.Replace("/", "\\");//模板物理路径
FileSystem fs = new FileSystem();
return fs.ReadTxtFile(physicfile, Encoding.UTF8);
}
else
return "";
}
//获取网页头部模板内容
public virtual string GetPageHeadArea()
{
string cachekey = "commpagehead";
string headinfo = "";
if (CommTool.Caches.CommonCache.Cache[cachekey] != null)
{
headinfo = (string)CommTool.Caches.CommonCache.Cache[cachekey];
}
else
{
//从模版读取文件数据
FileSystem fs=new FileSystem();
headinfo = fs.ReadTxtFile(SitePathHelper.GetModelFilePhysicalPath() +
"\\models\\2014Models\\pageheadmodel.html", Encoding.UTF8);
CommTool.Caches.CommonCache.Cache.Insert(cachekey, headinfo, null,
DateTime.Now.AddMinutes(3),
System.Web.Caching.Cache.NoSlidingExpiration,
System.Web.Caching.CacheItemPriority.Normal, null);
}
return headinfo;
}
//获取网页尾部模板内容
public virtual string GetPageBottomArea()
{
return "<script type=\"text/javascript\" src=\"http://www.e-works.net.cn/js/foot2014.js\"></script>";
}
//网页用于Seo的title
public virtual string GetSeoTitle()
{
if (Config != null)
return Config.Title;
else
return "";
}
//网页用于seo的关键字
public virtual string GetSeoKeywords()
{
if (Config != null)
return Config.KeyWord;
else
return "";
}
//网页用于seo的描述
public virtual string GetSeoDescrption()
{
if (Config != null)
return Config.Descrption;
else
return "";
}
//替换广告内容
public virtual string ReplaceAdInfo(string modelinfo)
{
if (Config != null)
{
int adprojectid = Config.AdProjectid;
if(adprojectid>0)
{
IAdProjectManage projectmanage = new AdProjectManageBL();
List<Ewk_adViewForCreate> lists = projectmanage.GetAdProjectDetailForCreate(adprojectid);
String adimage;
String href = "";
if (lists.Count > 0)
{
foreach (Ewk_adViewForCreate item in lists)
{
if (item.Ad_type == 0)
{
adimage = "<img src=\"http://www.e-works.net.cn/AdRotators/images/project/" + item.Ad_imageurl + " \" border=0 width=\"" + item.Width + " \" height=\"" + item.Height + "\">";
href = "<a href=\"" + item.Ad_url + " \" target='_blank'>" + adimage + "</a>";
}
else if (item.Ad_type == 1)
{
href = "";
href += "<object type=\"application/x-shockwave-flash\" width=\"" +
item.Width + "\" height=\"" + item.Height + "\" data=\"http://www.e-works.net.cn/AdRotators/images/project/" + item.Ad_imageurl + "\"> <param name=\"wmode\" value=\"Opaque\" />\n";
href += "<param name=\"movie\" value=\"http://www.e-works.net.cn/AdRotators/images/project/" + item.Ad_imageurl + "\" />\n";
href += "</object>";
}
else
{
href = item.Ad_code;
}
String oldvalue = "<!--#" + item.Ad_name + "-->";
modelinfo = modelinfo.Replace(oldvalue, href);
}
}
}
}
return modelinfo;
}
//文章内容信息处理
public abstract void DealHtmlModelAndCreate(string modelinfo, int topicId, int objectid, string webRootPath);
}
}
写完了抽象类,大家肯定知道需要写具体的网页生成类来继承它,下面是一个简单的文章列表页面生成类的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CommTool;
using IDAL.CreatePage;
using Dal.CreatePage;
using EworksCms.Domain;
using EworksCms.Domain.CreatePage;
using Framework.CreatePageHelper;
namespace Framework.CreatePage
{
public class ArticleSecondCreate : AbstractEworksCreatePage
{
public override string GetPageHeadArea()
{
string headinfo = ArticleCreateCommMethod.GetArticlesHeadArea();
return headinfo;
}
public override void DealHtmlModelAndCreate(string modelinfo, int topicId, int objectid, string webRootPath)
{
//获取文库相关的栏目序号
List<Ewk_Content_TopicView> allarticles = ContentTopicHelper.ListChildTopicList(11, "48,377,674");
//获取对应大类,所有的子类数据
var tempchild = from d in allarticles
where d.Content_topic_uid == topicId
select d;
string childtopicids = "";
StringBuilder sb = new StringBuilder();
foreach (Ewk_Content_TopicView item in tempchild)
{
sb.Append(item.Content_topic_id + ",");
}
childtopicids = sb.ToString();
if (childtopicids.Length > 0)
childtopicids = childtopicids.Substring(0, childtopicids.Length - 1);
IArticleSecondListCreate secondcreate = new ArticleSecondListCreate();
ArticleSecondListCreateData dateinfo = secondcreate.GetArticleSecondListData(topicId, childtopicids);
//替换掉数据
//4个排行榜
下面省去若干行。。。
}
}
}
这个类继承了上面的抽象类,并复写了抽象类中的虚方法。至此我们实现了面向对象三大特性中的继承还有多态,但是说好的封装呢?还有可扩展性呢?五大原则都遵循了吗?别急,我们的程序还没完,程序如果写成这个样子,封装性太差,客户程序调用的时候很麻烦,根本不敢拿出来秀。
为了让程序有好的封装性,客户有统一的调用接口,以及满足面向抽象编程、面向接口编程的原则;对修改关闭,对扩展开发的原则,我们给程序加一个辅助类来包装一下程序。代码如下:
这个类中最重要的一个方法就是:
public static void CreatePage(EworksCreateTopicConfig config,AbstractEworksCreatePage createpagedetail, int objectid,string webRootPath).
它的第二个参数类型是网页生成方法的抽象类:AbstractEworksCreatePage ,其实就相当于一个接口,客户程序调用的时候可以把自己的网页生成类传递进来,比如生成文章列表页面就可以象下面那样调用: EworksCreatePageHelper.CreatePage(EworksCreateTopicConfigHelper.GetEworksCreateTopicConfig(id), ArticleListCreate(), 0, SitePathHelper.GetWebSitePhysicalPath() + "\\articles\\");
有了帮助类以后,程序就有了较好的封装性,系统暴露给外部程序的调用接口形式是一致的,如果你要生成新闻页面,程序还是调用 EworksCreatePageHelper.CreatePage方法,你只要AbstractEworksCreatePage 参数换成生成新闻页面的类就行了。
至此本程序已经实现面向对象编程的三大特性。