CSharp: Strategy Pattern
/// <summary> /// A simple file handlng class /// Strategy Pattern 策略模式 ///20220918 /// geovindu,Geovin Du,涂聚文 /// </summary> public class csFile { private string fileName; StreamReader ts; StreamWriter ws; /// <summary> /// /// </summary> private bool opened, writeOpened; /// <summary> /// /// </summary> public csFile() { init(); } /// <summary> /// /// </summary> private void init() { opened = false; writeOpened = false; } /// <summary> /// /// </summary> /// <param name="file_name"></param> public csFile(string file_name) { fileName = file_name; init(); } /// <summary> /// /// </summary> /// <param name="file_name"></param> /// <returns></returns> public bool OpenForRead(string file_name) { fileName = file_name; try { ts = new StreamReader(fileName); opened = true; } catch (FileNotFoundException) { return false; } return true; } /// <summary> /// /// </summary> /// <returns></returns> public bool OpenForRead() { return OpenForRead(fileName); } /// <summary> /// /// </summary> /// <returns></returns> public string readLine() { return ts.ReadLine(); } /// <summary> /// /// </summary> /// <param name="s"></param> public void writeLine(string s) { ws.WriteLine(s); } /// <summary> /// /// </summary> public void close() { if (opened) ts.Close(); if (writeOpened) ws.Close(); } /// <summary> /// /// </summary> /// <returns></returns> public bool OpenForWrite() { return OpenForWrite(fileName); } /// <summary> /// /// </summary> /// <param name="file_name"></param> /// <returns></returns> public bool OpenForWrite(string file_name) { try { ws = new StreamWriter(file_name); fileName = file_name; writeOpened = true; return true; } catch (FileNotFoundException) { return false; } } }
/// <summary> /// String Tokenizer class /// Strategy Pattern 策略模式 ///20220918 /// geovindu,Geovin Du,涂聚文 /// </summary> public class StringTokenizer { private string data, delimiter; private string[] tokens; private int index; /// <summary> /// /// </summary> /// <param name="dataLine"></param> public StringTokenizer(string dataLine) { init(dataLine, " "); } /// <summary> /// /// </summary> /// <param name="dataLine"></param> /// <param name="delim"></param> private void init(String dataLine, string delim) { delimiter = delim; data = dataLine; tokens = data.Split(delimiter.ToCharArray()); index = 0; } /// <summary> /// /// </summary> /// <param name="dataLine"></param> /// <param name="delim"></param> public StringTokenizer(string dataLine, string delim) { init(dataLine, delim); } /// <summary> /// /// </summary> /// <returns></returns> public bool hasMoreElements() { return (index < (tokens.Length)); } /// <summary> /// /// </summary> /// <returns></returns> public string nextToken() { return nextElement(); } /// <summary> /// /// </summary> /// <returns></returns> public string nextElement() { string s = tokens[index++]; while ((s.Length <= 0) && (index < tokens.Length)) s = tokens[index++]; return s; } }
/// <summary> /// Command interface /// Strategy Pattern 策略模式 ///20220918 /// geovindu,Geovin Du,涂聚文 /// </summary> public interface Command { void Execute(); }
/// <summary> /// Selects which plot strategy to carry out /// Strategy Pattern 策略模式 ///20220918 /// geovindu,Geovin Du,涂聚文 /// </summary> public class Context { float[] x, y; PlotStrategy plts; //strategy selected goes here /// <summary> /// ----- /// </summary> public void plot() { readFile(); //read in data plts.plot(x, y); } /// <summary> /// select bar plot /// </summary> public void setBarPlot() { plts = new BarPlotStrategy(); } /// <summary> /// select line plot /// </summary> public void setLinePlot() { plts = new LinePlotStrategy(); } /// <summary> /// /// </summary> public void readFile() { ArrayList xc = new ArrayList(); ArrayList yc = new ArrayList(); //reads data in from data file csFile fl = new csFile("data.txt"); fl.OpenForRead(); string sline = fl.readLine(); while (sline != null) { int i = sline.IndexOf(" "); if (i > 0) { float tmp = Convert.ToSingle(sline.Substring(0, i)); xc.Add(tmp); tmp = Convert.ToSingle(sline.Substring(i + 1)); yc.Add(tmp); } sline = fl.readLine(); } //copy into arrays from collections float[] xp = new float[xc.Count]; float[] yp = new float[yc.Count]; for (int i = 0; i < xc.Count; i++) { xp[i] = (float)xc[i]; yp[i] = (float)yc[i]; } x = xp; y = yp; fl.close(); } }
/// <summary> /// Summary description for PlotStrategy. /// Strategy Pattern 策略模式 ///20220918 /// geovindu,Geovin Du,涂聚文 /// </summary> public abstract class PlotStrategy { public abstract void plot(float[] x, float[] y); }
/// <summary> /// Summary description for LinePlotStrategy. /// Strategy Pattern 策略模式 ///20220918 /// geovindu,Geovin Du,涂聚文 /// </summary> public class LinePlotStrategy : PlotStrategy { /// <summary> /// /// </summary> /// <param name="x"></param> /// <param name="y"></param> public override void plot(float[] x, float[] y) { LinePlotForm lplt = new LinePlotForm(); lplt.Show(); lplt.plot(x, y); } }
/// <summary> /// Summary description for BarPlotStrategy. /// Strategy Pattern 策略模式 ///20220918 /// geovindu,Geovin Du,涂聚文 /// </summary> public class BarPlotStrategy : PlotStrategy { public override void plot(float[] xp, float[] yp) { BarPlotForm bplot = new BarPlotForm(); bplot.Show(); bplot.plot(xp, yp); } }
/// <summary> /// Strategy Pattern 策略模式 ///20220918 /// geovindu,Geovin Du,涂聚文 /// </summary> public partial class BarButton : System.Windows.Forms.Button, Command { /// <summary> /// /// </summary> private Context contxt; /// <summary> /// /// </summary> /// <param name="ctx"></param> public void setContext(Context ctx) { contxt = ctx; } public void Execute() { contxt.setBarPlot(); contxt.plot(); } /// <summary> /// /// </summary> public BarButton() { InitializeComponent(); } /// <summary> /// /// </summary> /// <param name="container"></param> public BarButton(IContainer container) { container.Add(this); InitializeComponent(); } }
/// <summary> /// Strategy Pattern 策略模式 ///20220918 /// geovindu,Geovin Du,涂聚文 /// </summary> public partial class LineButton : System.Windows.Forms.Button, Command { /// <summary> /// /// </summary> private Context contxt; /// <summary> /// /// </summary> /// <param name="ctx"></param> public void setContext(Context ctx) { contxt = ctx; } /// <summary> /// /// </summary> public void Execute() { contxt.setLinePlot(); contxt.plot(); } /// <summary> /// /// </summary> public LineButton() { InitializeComponent(); this.Text = "Line plot"; } /// <summary> /// /// </summary> /// <param name="container"></param> public LineButton(IContainer container) { container.Add(this); InitializeComponent(); } }
/// <summary> /// Strategy Pattern 策略模式 ///20220918 /// geovindu,Geovin Du,涂聚文 /// </summary> public partial class BarPlotForm : Form { protected float ymin, ymax, xfactor, yfactor; protected float xpmin, xpmax, ypmin, ypmax, xp, yp; private float xmin, xmax; private int w, h; protected float[] x, y; private ArrayList colors; protected Pen bPen; protected bool hasData; protected const float max = 1.0e38f; /// <summary> /// /// </summary> /// <param name="xp"></param> /// <param name="yp"></param> public void plot(float[] xp, float[] yp) { x = xp; y = yp; setPlotBounds(); //compute scaling factors hasData = true; pic.Refresh(); } /// <summary> /// /// </summary> public void findBounds() { xmin = max; xmax = -max; ymin = max; ymax = -max; for (int i = 0; i < x.Length; i++) { if (x[i] > xmax) xmax = x[i]; if (x[i] < xmin) xmin = x[i]; if (y[i] > ymax) ymax = y[i]; if (y[i] < ymin) ymin = y[i]; } } /// <summary> /// /// </summary> public virtual void setPlotBounds() { findBounds(); //compute scaling factors h = pic.Height; w = pic.Width; xfactor = 0.8F * w / (xmax - xmin); xpmin = 0.05F * w; xpmax = w - xpmin; yfactor = 0.9F * h / (ymax - ymin); ypmin = 0.05F * h; ypmax = h - ypmin; //create array of colors for bars colors = new ArrayList(); colors.Add(new SolidBrush(Color.Red)); colors.Add(new SolidBrush(Color.Green)); colors.Add(new SolidBrush(Color.Blue)); colors.Add(new SolidBrush(Color.Magenta)); colors.Add(new SolidBrush(Color.Yellow)); } /// <summary> /// /// </summary> /// <param name="xp"></param> /// <returns></returns> public int calcx(float xp) { int ix = (int)((xp - xmin) * xfactor + xpmin); return ix; } /// <summary> /// /// </summary> /// <param name="yp"></param> /// <returns></returns> public int calcy(float yp) { yp = ((yp - ymin) * yfactor); int iy = h - (int)(ypmax - yp); return iy; } /// <summary> /// /// </summary> public BarPlotForm() { InitializeComponent(); this.Text = "Bar Plot"; } /// <summary> /// /// </summary> /// <param name="container"></param> public BarPlotForm(IContainer container) { container.Add(this); InitializeComponent(); } /// <summary> /// /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void BarPlotForm_Load(object sender, EventArgs e) { } /// <summary> /// LinePlotForm需要重写此方法 /// /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected virtual void pic_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; if (hasData) { for (int i = 0; i < x.Length; i++) { int ix = calcx(x[i]); int iy = calcy(y[i]); Brush br = (Brush)colors[i]; g.FillRectangle(br, ix, h - iy, 20, iy); } } } }
/// <summary> /// Strategy Pattern 策略模式 ///20220918 /// geovindu,Geovin Du,涂聚文 /// </summary> public partial class LinePlotForm : BarPlotForm { /// <summary> /// /// </summary> public LinePlotForm() { init(); //InitializeComponent(); } /// <summary> /// /// </summary> protected void init() { bPen = new Pen(Color.Black); this.Text = "Line Plot"; } /// <summary> /// 重写BarPlotForm的方法 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected override void pic_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; if (hasData) { for (int i = 1; i < x.Length; i++) { int ix = calcx(x[i - 1]); int iy = calcy(y[i - 1]); int ix1 = calcx(x[i]); int iy1 = calcy(y[i]); g.DrawLine(bPen, ix, iy, ix1, iy1); } } } /// <summary> /// /// </summary> private void InitializeComponent() { this.SuspendLayout(); // // LinePlotForm // this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 18F); this.ClientSize = new System.Drawing.Size(678, 702); this.Name = "LinePlotForm"; this.Load += new System.EventHandler(this.LinePlotForm_Load); //this.Paint += new System.Windows.Forms.PaintEventHandler(this.LinePlotForm_Paint); this.ResumeLayout(false); } /// <summary> /// /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void LinePlotForm_Load(object sender, EventArgs e) { } /// <summary> /// 在窗体画 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void LinePlotForm_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; if (hasData) { for (int i = 1; i < x.Length; i++) { int ix = calcx(x[i - 1]); int iy = calcy(y[i - 1]); int ix1 = calcx(x[i]); int iy1 = calcy(y[i]); g.DrawLine(bPen, ix, iy, ix1, iy1); } } } }
调用:
/// <summary> /// Strategy Pattern 策略模式 ///20220918 /// geovindu,Geovin Du,涂聚文 /// </summary> public partial class StrategyPatternForm : Form { private void init() { EventHandler evh = new EventHandler(ButtonClick); btLine.Click += evh; btBar.Click += evh; Context contxt = new Context(); btBar.setContext(contxt); btLine.setContext(contxt); } /// <summary> /// /// </summary> public StrategyPatternForm() { InitializeComponent(); init(); } /// <summary> /// /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void StrategyPatternForm_Load(object sender, EventArgs e) { } /// <summary> /// /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void ButtonClick(object sender, System.EventArgs e) { Command comd = (Command)sender; comd.Execute(); } }
data:
1 20 2 35 3 13 4 52 5 44
输出:
哲学管理(学)人生, 文学艺术生活, 自动(计算机学)物理(学)工作, 生物(学)化学逆境, 历史(学)测绘(学)时间, 经济(学)数学金钱(理财), 心理(学)医学情绪, 诗词美容情感, 美学建筑(学)家园, 解构建构(分析)整合学习, 智商情商(IQ、EQ)运筹(学)生存.---Geovin Du(涂聚文)