C#设计模式之23——模板方法模式

模板方法模式是非常简单的一个模式。任何时候只要你编写了一个父类,并在类中留有一个或者多个方法给派生类实现,实质上就是在使用模板模式。模板模式形式化了在类中定义算法但是把算法的实现细节留个子类实现这一想法。

模板方法模式有四种可能在派生类中使用的方法:

1. 完整的方法,这些方法可以被派生类继承。

2.完全没有填写的方法,方法主体为空。

3. 包含某些操作的默认实现的方法,但是有可能在派生类中被重写。这种方法被称为钩子。

4. 其本身使用了抽象,钩子和具体方法的任意组合的方法。

 

假设我们有一个程序,在用户界面绘制三角形。

用户界面如图:

 

我们有一个抽象类Triangle类说明模式:

using System;
using System.Drawing ;

namespace Template
{
	/// <summary>
	/// Summary description for Triangle.
	/// </summary>
	public abstract class Triangle 	{
		private Point p1, p2, p3;
		protected Pen pen;
		//-----
		public Triangle(Point a, Point b, Point c) 	{
			p1 = a;
			p2 =  b;
			p3 = c;
			pen = new Pen(Color.Black , 1);
		}
		//-----
		public virtual void draw(Graphics g) {
			g.DrawLine (pen, p1, p2);
			Point c = draw2ndLine(g, p2, p3);
			closeTriangle(g, c);
		}
		//-----
		public abstract Point draw2ndLine(Graphics g, Point a, Point b);
		//-----
		public void closeTriangle(Graphics g, Point c) {
			g.DrawLine (pen, c, p1);
		}
	}
}


 

这里有个函数留给了派生类来实现,不同的派生类根据需要可以绘制不同的三角形。

两个派生类的实现,一个是普通的三角形,一个是等腰三角形类。

using System;
using System.Drawing ;
namespace Template
{
	/// <summary>
	/// Summary description for StdTriangle.
	/// </summary>
	public class StdTriangle :Triangle 	{
		public StdTriangle(Point a, Point b, Point c) : base(a, b, c) {}
		//------
		public override Point draw2ndLine(Graphics g, Point a, Point b) {
			g.DrawLine (pen, a, b);
			return b;
		}
	}
}


 

using System;
using System.Drawing;
namespace Template
{
	/// <summary>
	/// Summary description for IsocelesTriangle.
	/// </summary>
	public class IsocelesTriangle : Triangle 	{
		private Point newc;
		private int newcx, newcy;
		//-----
		public IsocelesTriangle(Point a, Point b, Point c) :base(a, b, c) {
			float dx1, dy1, dx2, dy2, side1, side2;
			float slope, intercept;
            int incr;
			dx1 = b.X - a.X;
			dy1 = b.Y - a.Y;
			dx2 = c.X  - b.X;
			dy2 = c.Y - b.Y;
        
			side1 = calcSide(dx1, dy1);
			side2 = calcSide(dx2, dy2);
        
			if (side2 < side1) 
				incr = -1;
			else
				incr = 1;
			slope = dy2 / dx2;
			intercept = c.Y - slope * c.X;
        
			//move point c so that this is an isoceles triangle
			newcx = c.X;
			newcy = c.Y;
			while (Math.Abs (side1 - side2) > 1) {
				newcx = newcx + incr;    //iterate a pixel at a time until close
				newcy = (int)(slope * newcx + intercept);
				dx2 = newcx - b.X;
				dy2 = newcy - b.Y;
				side2 = calcSide(dx2, dy2);
			}
			newc = new Point(newcx, newcy);
		}
		//-----
		private float calcSide(float a, float b) {
			return (float)Math.Sqrt (a*a +  b*b);
		}
		//-----
		public override Point draw2ndLine(Graphics g, Point b, Point  c) {
			g.DrawLine (pen, b, newc);
			return newc;
		}

	}
}


 

然后就是主程序的调用:

private ArrayList triangles;
		public Form1()
		{
			InitializeComponent();
			init();
			
		}
		private void init() {
			triangles = new ArrayList();
			StdTriangle t1 = new StdTriangle(new Point(10, 10), 
				new Point(150, 50), 
				new Point(100, 75));
			IsocelesTriangle t2 = new IsocelesTriangle( 
				new Point(150, 100), new Point(240, 40), 
				new Point(175, 150));
			triangles.Add(t1);
			triangles.Add(t2);
			Pic.Paint+= new PaintEventHandler (TPaint);
		}


 

private void TPaint (object sender,  System.Windows.Forms.PaintEventArgs e ) {
			Graphics g = e.Graphics;
			for (int i = 0; i<  triangles.Count ; i++) {
				Triangle t = (Triangle)triangles[i];
				t.draw(g);
			}
		}


模板模式始终在OO软件中存在,他们就是OO编程的普通组成部分。基类只能定义某些它将要用到的方法,而把其余部分留给派生类来实现。

这个设计模式更多的是面向对象编程的思想基础,比较简单。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值