封装变化(Part One)
软件设计最大的敌人,就是应付需求不断的变化。变化有时候是无穷尽的,于是项目开发就在反复的修改、更新中无限期地延迟交付的日期。变化如悬在头顶的达摩克斯之剑,令许多软件工程专家一筹莫展。正如无法找到解决软件开发的“银弹”,要彻底将变化扼杀在摇篮之中,看来也是不可能完成的任务。那么,积极地面对“变化”,方才是可取的态度。于是,极限编程(XP)的倡导者与布道者Kent Beck提出要“拥抱变化”,从软件工程方法的角度,提出了应对“变化”的解决方案。而本文则试图从软件设计方法的角度,来探讨如何在软件设计过程中,解决未来可能的变化,其方法就是——封装变化。
设计模式是“封装变化”方法的最佳阐释。无论是创建型模式、结构型模式还是行为型模式,归根结底都是寻找软件中可能存在的“变化”,然后利用抽象的方式对这些变化进行封装。由于抽象没有具体的实现,就代表了一种无限的可能性,使得其扩展成为了可能。所以,我们在设计之初,除了要实现需求所设定的用例之外,还需要标定可能或已经存在的“变化”之处。封装变化,最重要的一点就是发现变化,或者说是寻找变化。
GOF对设计模式的分类,已经彰显了“封装变化”的内涵与精髓。创建型模式的目的就是封装对象创建的变化。例如Factory Method模式和Abstract Factory模式,建立了专门的抽象的工厂类,以此来封装未来对象的创建所引起的可能变化。而Builder模式则是对对象内部的创建进行封装,由于细节对抽象的可替换性,使得将来面对对象内部创建方式的变化,可以灵活的进行扩展或替换。
至于结构型模式,它关注的是对象之间组合的方式。本质上说,如果对象结构可能存在变化,主要在于其依赖关系的改变。当然对于结构型模式来说,处理变化的方式不仅仅是封装与抽象那么简单,还要合理地利用继承与聚合的方法,灵活地表达对象之间的依赖关系。例如Decorator模式,描述的就是对象间可能存在的多种组合方式,这种组合方式是一种装饰者与被装饰者之间的关系,因此封装这种组合方式,抽象出专门的装饰对象显然正是“封装变化”的体现。同样地,Bridge模式封装的则是对象实现的依赖关系,而Composite模式所要解决的则是对象间存在的递归关系。
行为型模式关注的是对象的行为。行为型模式需要做的是对变化的行为进行抽象,通过封装以达到整个架构的可扩展性。例如策略模式,就是将可能存在变化的策略或算法抽象为一个独立的接口或抽象类,以实现策略扩展的目的。Command模式、State模式、Vistor模式、Iterator模式概莫如是。或者封装一个请求(Command模式),或者封装一种状态(State模式),或者封装“访问”的方式(Visitor模式),或者封装“遍历”算法(Iterator模式)。而这些所要封装的行为,恰恰是软件架构中最不稳定的部分,其扩展的可能性也最大。将这些行为封装起来,利用抽象的特性,就提供了扩展的可能。
利用设计模式,通过封装变化的方法,可以最大限度的保证软件的可扩展性。面对纷繁复杂的需求变化,虽然不可能完全解决因为变化带来的可怕梦魇,然而,如能在设计之初预见某些变化,仍有可能在一定程度上避免未来存在的变化为软件架构带来的灾难性伤害。从此点看,虽然没有“银弹”,但从软件设计方法的角度来看,设计模式也是一枚不错的“铜弹”了。
刷新aspx页面的六种方法
private void Button1_Click(object sender, System.EventArgs e)
{
Response.Redirect(Request.Url.ToString());
}
第二:
private void Button2_Click(object sender, System.EventArgs e)
{
Response.Write(<script language=javascript>window.location.href=document.URL;</script>);
}
第三:
private void Button3_Click(object sender, System.EventArgs e)
{
Response.AddHeader(Refresh,0);
}
第四:
private void Button6_Click(object sender, System.EventArgs e)
{
}
第五:(需替换《》)
《script》
<!--
var parselimit=limit.split(:)
parselimit=parselimit[0]*60+parselimit[1]*1
}
function beginrefresh(){
if (!document.images)
return
if (parselimit==1)
window.location.reload()
else{
parselimit-=1
curmin=Math.floor(parselimit/60)
cursec=parselimit%60
if (curmin!=0)
curtime=curmin+分+cursec+秒后重刷本页!
else
curtime=cursec+秒后重刷本页!
window.status=curtime
setTimeout(beginrefresh(),1000)
}
}
window.οnlοad=beginrefresh
//-->
</script>
<DIV style=Z-INDEX: 102; LEFT: 408px; POSITION: absolute; TOP: 232px ms_positioning=text2D>
<P><FONT size=3>自动刷新页面</FONT></P>
</DIV>
第六:
<meta http-equiv=refresh content=300; url=target.html>
showModalDialog 模态打开子窗体,返回值到父窗体
其中javascirpt 脚本如下:
{
var aa=window.showModalDialog(strUrl,null,'dialogWidth:400px;dialogHeight:100px;center:yes;status:no;dialogWidth:400px;dialogHeight:300px');
if (aa!=null)
{
document.all.txt_Send_Email.value=aa
}
}
如果需要把txt_Send_Email的readonly设置为true 则,需要增加C#代码:
javascript 里面执行单击按钮操作
// btn_get_value 是按钮名称
后台C#程序如下:
打开子页面:frmChoose_UserForMail.aspx
子页面(功能:实现关闭子页面,并且返回数据):
Page.RegisterClientScriptBlock( " Close " , strScr);
关闭页面脚本:
Response.Write(str_strScr);
Response.Write(str_strScr);
2005里面验证通过
下面的代码可以好好研究研究
function BtnChooseApprover()
{
var obj = new Object();
obj.workflowstatue=document.getElementById("txtworkflow").value;
obj.userid=document.getElementById("txtuserid").value;
var re = window.showModalDialog("Default.aspx",obj,"center:yes;dialogHeight:500px;dialogWidth:400px;scroll:no");
this.txtApprovers.Text=re;
}
</ script >
文件上传的一段事例代码
protected string imagePath; //图片路径
protected string imageType; //图片类型
protected string imageName;
protected System.Web.UI.WebControls.RadioButtonList choice; //图片名称
System.Drawing.Image.GetThumbnailImageAbort callb =null; //提供一个回调方法,用于确定Image对象在执行生成缩略图操作时何时提前取消执行,如果此方法确定GetThumbnailImage方法应提前停止执行,则返回true,否则返回false
CODE: [Copy to clipboard]
--------------------------------------------------------------------------------
{
string mPath,img_source,img_small;
string pid = Request.QueryString["pid"];
string typeid = Request.QueryString["typeid"];
string typef = Request.QueryString["typef"];
{
imagePath = upImage.PostedFile.FileName;
//取得图片类型
imageType = imagePath.Substring(imagePath.LastIndexOf(".")+1);
//取得图片名称
imageName = DateTime.Now.Year.ToString()+DateTime.Now.Month.ToString()+DateTime.Now.Day.ToString()+DateTime.Now.Hour.ToString()+DateTime.Now.Minute.ToString()+DateTime.Now.Second.ToString()+imagePath.Substring(imagePath.LastIndexOf(" //")+1);
if("jpg"!= imageType && "gif"!= imageType )
{
Response.Write("<script language='javascript'>alert('对不起!请您选择jpg或者gif格式的图片!');</script>");
return;
}
else
{
mPath = Server.MapPath("../../picture"); //建立虚拟路径
upImage.PostedFile.SaveAs(mPath+" //"+imageName); //保存到虚拟路径
img_source = "picture/" + imageName; //显示原图
image = System.Drawing.Image.FromFile(mPath+" //"+imageName); //为上传的图片建立引用
newimage = image.GetThumbnailImage(184,148,callb,new System.IntPtr()); //生成缩略图
newimage.Save(Server.MapPath("../../picture")+" //small"+imageName); //把缩略图保存到指定的虚拟路径
image.Dispose(); //释放image对象占用的资源
newimage.Dispose(); //释放newimage对象的资源
img_small = "picture/" + "small" + imageName; //显示缩略图
string imgid = pub.AddImage(txt_name.Text,img_source,img_small,txt_author.Text,Int32.Parse(pid),Int32.Parse(typeid));
if (imgid != "")
{
string UserChoice = choice.SelectedValue;
switch(UserChoice)
{
case "1":
Response.Redirect ("index.aspx?typeid="+typeid+"&typef="+typef+"&pid="+pid+"");
break;
case "2":
{
txt_name.Text = "";
txt_author.Text = "";
}
break;
}
}
else
{
txtMessage.Text ="不好意思,上传图片失败!";
}
}
}
<%@ Page language="c#" Codebehind="UpLoad.aspx.cs" AutoEventWireup="false" Inherits="WebPortal.Upload" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
<HEAD>
<title>多文件上传</title>
<script language="JavaScript">
function addFile()
{
var str = '<INPUT type="file" size="50" NAME="File">'
document.getElementById('MyFile').insertAdjacentHTML("beforeEnd",str)
}
</script>
</HEAD>
<body>
<form id="form1" method="post" runat="server" enctype="multipart/form-data">
<div align="center">
<h3>多文件上传</h3>
<P id="MyFile"><INPUT type="file" size="50" NAME="File"></P>
<P>
<input type="button" value="增加(Add)" οnclick="addFile()"> <input οnclick="this.form.reset()" type="button" value="重置(ReSet)">
<asp:Button Runat="server" Text="开始上传" ID="UploadButton"></asp:Button>
</P>
<P>
<asp:Label id="strStatus" runat="server" Font-Names="宋体" Font-Bold="True" Font-Size="9pt" Width="500px"
BorderStyle="None" BorderColor="White"></asp:Label>
</P>
</div>
</form>
</body>
</HTML>
代码部分
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
namespace WebPortal
{
/// <summary>
/// UpLoad 的摘要说明。
/// 实现多文件上传
/// </summary>
public class Upload : System.Web.UI.Page
{
protected System.Web.UI.WebControls.Button UploadButton;
protected System.Web.UI.WebControls.Label strStatus;
private void Page_Load(object sender, System.EventArgs e)
{
/// 在此处放置用户代码以初始化页面
if (this.IsPostBack) this.SaveImages();
}
private Boolean SaveImages()
{
///'遍历File表单元素
HttpFileCollection files = HttpContext.Current.Request.Files;
/// '状态信息
System.Text.StringBuilder strMsg = new System.Text.StringBuilder();
strMsg.Append("上传的文件分别是:<hr color=red>");
try
{
for(int iFile = 0; iFile < files.Count; iFile++)
{
///'检查文件扩展名字
HttpPostedFile postedFile = files[iFile];
string fileName, fileExtension;
fileName = System.IO.Path.GetFileName(postedFile.FileName);
if (fileName != "")
{
fileExtension = System.IO.Path.GetExtension(fileName);
strMsg.Append("上传的文件类型:" + postedFile.ContentType.ToString() + "<br/>");
strMsg.Append("客户端文件地址:" + postedFile.FileName + "<br/>");
strMsg.Append("上传文件的文件名:" + fileName + "<br/>");
strMsg.Append("上传文件的扩展名:" + fileExtension + "<br/><hr>");
///'可根据扩展名字的不同保存到不同的文件夹
///注意:可能要修改你的文件夹的匿名写入权限。
postedFile.SaveAs(System.Web.HttpContext.Current.Request.MapPath("images/") + fileName);
}
}
strStatus.Text = strMsg.ToString();
return true;
}
catch(System.Exception Ex)
{
strStatus.Text = Ex.Message;
return false;
}
}
#region Web 窗体设计器生成的代码
override protected void OnInit(EventArgs e)
{
//
// CODEGEN: 该调用是 ASP.NET Web 窗体设计器所必需的。
//
InitializeComponent();
base.OnInit(e);
}
/// <summary>
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
/// 此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.ID = "Upload";
this.Load += new System.EventHandler(this.Page_Load);
}
#endregion
}
}
用ASP.NET把图象追加到数据库(3)
鉴于问的人较多,先贴出代码
Image2Access.aspx 上传文件到 Access 数据库
上传文件到 Access 数据库
文件名字:文件:
Image2Access.aspx.csusing System; using System.Collections; using System.ComponentModel; using System.Data; using System.Data.OleDb; using System.Drawing; using System.Web; using System.IO; using System.Web.SessionState; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.HtmlControls; namespace eMeng.Exam { /// /// Image2Access 的摘要说明。 /// public class Image2Access : System.Web.UI.Page { protected System.Web.UI.HtmlControls.HtmlInputText MyFileName; protected System.Web.UI.HtmlControls.HtmlInputFile MyFile; protected System.Web.UI.HtmlControls.HtmlInputButton Submit1; protected System.Web.UI.WebControls.DataGrid DG_Persons; private void Page_Load(object sender, System.EventArgs e) { // 在此处放置用户代码以初始化页面 BindGrid(); } private void BindGrid() { string strCnn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + Server.MapPath("Image2Access.mdb"); OleDbConnection myConnection = new OleDbConnection(strCnn); OleDbCommand myCommand = new OleDbCommand("SELECT * FROM Person", myConnection); myCommand.CommandType = CommandType.Text; try { myConnection.Open(); DG_Persons.DataSource = myCommand.ExecuteReader(CommandBehavior.CloseConnection); DG_Persons.DataBind(); } catch(OleDbException SQLexc) { Response.Write("提取数据时出现错误:" + SQLexc.ToString()); } } protected string FormatURL(object strArgument) { return "ReadImage.aspx?id=" + strArgument.ToString(); } #region Web 窗体设计器生成的代码 override protected void OnInit(EventArgs e) { // // CODEGEN: 该调用是 ASP.NET Web 窗体设计器所必需的。 // InitializeComponent(); base.OnInit(e); } /// /// 设计器支持所需的方法 - 不要使用代码编辑器修改 /// 此方法的内容。 /// private void InitializeComponent() { this.Submit1.ServerClick += new System.EventHandler(this.Submit1_ServerClick); this.Load += new System.EventHandler(this.Page_Load); } #endregion private void Submit1_ServerClick(object sender, System.EventArgs e) { //得到提交的文件 Stream fileDataStream = MyFile.PostedFile.InputStream; //得到文件大小 int fileLength = MyFile.PostedFile.ContentLength; //创建数组 byte[] fileData = new byte[fileLength]; //把文件流填充到数组 fileDataStream.Read(fileData,0,fileLength); //得到文件名字 string fileTitle = MyFileName.Value; //得到文件类型 string fileType = MyFile.PostedFile.ContentType; //构建数据库连接,SQL语句,创建参数 string strCnn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + Server.MapPath("Image2Access.mdb"); OleDbConnection myConnection = new OleDbConnection(strCnn); OleDbCommand command = new OleDbCommand ("INSERT INTO Person (PersonName,PersonEmail,PersonSex,PersonImageType,PersonImage)" + "VALUES (@PersonName,@PersonEmail,@PersonSex,@PersonImageType,@PersonImage)", myConnection); System.Data.OleDb.OleDbParameter paramPersonName = new OleDbParameter("@PersonName", System.Data.OleDb.OleDbType.VarChar,50); paramPersonName.Value = fileTitle; command.Parameters.Add(paramPersonName); System.Data.OleDb.OleDbParameter paramPersonEmail = new OleDbParameter("@PersonEmail", System.Data.OleDb.OleDbType.VarChar,50); paramPersonEmail.Value = "mengxianhui@dotnet.aspx.cc"; command.Parameters.Add(paramPersonEmail); System.Data.OleDb.OleDbParameter paramPersonSex = new OleDbParameter("@paramPersonSex", System.Data.OleDb.OleDbType.VarChar,50); paramPersonSex.Value = "男"; command.Parameters.Add(paramPersonSex); System.Data.OleDb.OleDbParameter paramPersonImageType = new OleDbParameter("@PersonImageType", System.Data.OleDb.OleDbType.VarChar,50); paramPersonImageType.Value = fileType; command.Parameters.Add(paramPersonImageType); System.Data.OleDb.OleDbParameter paramPersonImage = new OleDbParameter("@PersonImage", System.Data.OleDb.OleDbType.Binary); paramPersonImage.Value = fileData; command.Parameters.Add(paramPersonImage); //打开连接,执行查询 myConnection.Open(); command.ExecuteNonQuery(); myConnection.Close(); } } }