原型模式

这段时间在研究设计模式,前几天学习了原型模式,今天跟大家讨论下!

原型模式属于创建型模式,它与其他创建型模式不一样的是:它通过复制已有对象来产生新的对象。

1 结构图如下:

    在这里通过原型管理器去管理新生成的对象,用户不需要关心对象的生成细节。先注册原型类,再通过克隆原型生成具体的对象。与工厂方法模式相比,少了很多与产品平行的工厂方法类。

2 Demo设计图

    这几天做了一个与原型模式配套的小demo,请大家多多指教!

    这个小程序主要核心功能模块:画板、调色板、颜色管理器、颜色原型和具体颜色画笔。

 

3 代码实现

画板类实现:  

  画板根据调色板上选择的颜色,画出相应颜色的线,核心代码用到了画图的知识,这块也是现学现卖,写的不好的请大家指出!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using PrototypePattern.Color;
using System.Xml;
namespace PrototypePattern.Draw
{
    /// <summary>
    /// 画板类
    /// </summary>
    public class DrawBoard
    {

        private PictureBox pb;
        private Bitmap p_bmp;
        private Graphics dgGraphic;//画布
        private Palette palette;//调色板类,提供当前画笔(具体代码如下)
        private Point preP;

        public DrawBoard(ref PictureBox p, ref Palette palette)
        {
            this.palette = palette;

            this.pb = p;
            p_bmp = new Bitmap(this.pb.Width, this.pb.Height);
            dgGraphic = Graphics.FromImage(p_bmp);
            this.pb.Image = p_bmp;
            //设置鼠标形状
            this.pb.Cursor = Cursors.Cross;
        }

        public void DrawLine(Point ps, Point pd)
        {
            //擦除之前画的线
            dgGraphic.DrawLine(new Pen(this.pb.BackColor), ps, preP);
            dgGraphic.Clear(this.pb.BackColor);
            Pen p = palette.CurrentPen;
            p.Width = 3;
            dgGraphic.DrawLine(p, ps, pd);
            this.pb.Image = p_bmp;

            preP = pd;
        }

        ~DrawBoard()
        {
            if (dgGraphic != null)
                dgGraphic.Dispose();
        }
    }
}

调色板类实现:

  调色板聚合了颜色管理器,主要负责通过配置文件Colors.xml初始化颜色管理器,并在PictureBox呈现配置的颜色。用户可以选择相应的颜色,在画板中画出来。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using PrototypePattern.Color;
using System.Xml;
using System.Collections;

namespace PrototypePattern.Draw
{
    /// <summary>
    /// 调色板类
    /// </summary>
    public class Palette
    {
        private PictureBox pb;
        private Bitmap p_bmp;
        private Graphics dgGraphic;//画布
        private ColorManager colorsM=new ColorManager();//颜色管理器,用于管理封装的颜色对象聚集

        private Dictionary<string, Point> color_positions = new Dictionary<string, Point>();//存储颜色在调色板中的位置,该坐标为判断当前是否选中某种颜色使用。在初始化颜色聚集的时候,保存颜色初始位置。


        public int Width //颜色块的配置宽度
        {
            get;
            set;
        }

        public int Height //颜色块的配置高度
        {
            get;
            set;
        }
        
        public Palette(ref PictureBox p)
        {
            this.pb = p;
            p_bmp = new Bitmap(this.pb.Width, this.pb.Height);
            dgGraphic =Graphics.FromImage(p_bmp);
            this.pb.Image = p_bmp;
            colorsM = new ColorManager();
            //设置鼠标形状
            this.pb.Cursor = Cursors.Hand;
        }

        /// <summary>
        /// 初始化调色板(通过读取颜色配置文件Colors.xml初始化)
        /// </summary>
        /// <param name="filename"></param>
        /// <returns></returns>
        public bool InitializePalette(string filename)
        {
            try
            {
                XmlDocument xdoc = new XmlDocument();
                xdoc.Load(filename);
                XmlNodeList xlst= xdoc.GetElementsByTagName("color");

                Width = Convert.ToInt32(xdoc.SelectSingleNode("/Colors/width").InnerText);
                Height = Convert.ToInt32(xdoc.SelectSingleNode("/Colors/height").InnerText);

                foreach (XmlNode xn in xlst)
                {
                    XmlElement element = (XmlElement)xn;
                    int r=Convert.ToInt32(element.SelectSingleNode("r").InnerText);
                    int g=Convert.ToInt32(element.SelectSingleNode("g").InnerText);
                    int b=Convert.ToInt32(element.SelectSingleNode("b").InnerText);
                    colorsM[element.GetAttribute("name")]=new ConcreteColorPrototype(r,g,b).Clone();//通过克隆生成具体颜色对象,并由颜色管理器管理
                }                

                return true;

            }
            catch
            {
                throw new Exception("初始化调色板出错!");
            }
            
        }

        /// <summary>
        /// 绘制调色板
        /// </summary>
        public void Draw()
        {
            int p_width=this.pb.Width;
            int n = this.pb.Width / (Width + 2);
            int i = 0;
            int p_x = this.pb.Location.X, p_y = this.pb.Location.Y;
            int x = 0, y = 0;
            dgGraphic.Clear(this.pb.BackColor);
       //根据颜色管理器管理的颜色聚集,在调色板上绘制一个个颜色正方形
while (colorsM.MoveNext()) { y = i / n; x = i % n; int w=x * (Width + 2); int h=y * (Height + 2); color_positions.Add(colorsM.CurrentColor, new Point(w, h)); dgGraphic.FillRectangle(colorsM.Current, new Rectangle(w+5,h+5, Width, Height)); i++; } Point originP = color_positions[colorsM.CurrentColor]; dgGraphic.DrawRectangle(new Pen(Brushes.DeepPink, 1), originP.X - 1 + 5, originP.Y - 1 + 5, Width + 1, Height + 1); } /// <summary> /// 选中调色板颜色 /// </summary> /// <param name="p"></param> public void SelectColor(Point p) { Point originP = color_positions[colorsM.CurrentColor]; dgGraphic.DrawRectangle(new Pen(this.pb.BackColor,1), originP.X - 1+5, originP.Y - 1+5, Width + 1, Height + 1); foreach (KeyValuePair<string, Point> kv in color_positions) {
         //当用户单击颜色板时,通过鼠标当前坐标是否选中某种颜色,若在某种颜色方块颜色范围内就绘制选中的框,用于区别当前哪种颜色被选中
if(p.X>=kv.Value.X&&p.Y>=kv.Value.Y&&p.X<=(kv.Value.X+32)&&p.Y<=(kv.Value.Y+32)) { colorsM.CurrentColor = kv.Key; dgGraphic.DrawRectangle(new Pen(Brushes.DeepPink, 1), kv.Value.X - 1 + 5, kv.Value.Y - 1 + 5, Width + 1, Height + 1); pb.Image = p_bmp; break; } } } /// <summary> /// 返回当前画笔 /// </summary> public Pen CurrentPen { get {
         //根据颜色管理器当前颜色,生成画笔返回供画板划线使用 ConcreteColorPrototype ccp
=colorsM[colorsM.CurrentColor] as ConcreteColorPrototype; return new Pen(System.Drawing.Color.FromArgb(ccp.Red, ccp.Green, ccp.Blue)); } } ~Palette() { if (dgGraphic != null) dgGraphic.Dispose(); } } }

颜色管理器实现:

  颜色管理器的功能顾名思义就是管理颜色的,它封装了配置的颜色,并记录当前颜色,相关实现如下,欢迎大家提出意见!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Drawing;

namespace PrototypePattern.Color
{
    public class ColorManager
    {
     //用于存储颜色聚集
private Hashtable colors = new Hashtable();      //保存当前颜色名 private string currentColor; private string originColor; private int index=-1; private List<string> keys=new List<string>(); public List<string> Keys { get { return keys; } }     //给颜色聚集增加索引器 public ColorPrototype this[string name] { get { return colors[name] as ColorPrototype; } set { if (colors.Count == 0) { CurrentColor = name; originColor = name; } Keys.Add(name); colors.Add(name, value); } } public string CurrentColor { get { return currentColor; } set { currentColor = value; } } public Brush Current { get {
         //返回当前颜色块画刷 ConcreteColorPrototype ccp
=this[Keys[index]] as ConcreteColorPrototype; SolidBrush sb = new SolidBrush(System.Drawing.Color.FromArgb(ccp.Red, ccp.Green, ccp.Blue)); return sb; } } public bool MoveNext() { int len = Keys.Count; index++; if (index > len - 1) return false; currentColor = Keys[index]; return true; } public void Reset() { index = Keys.FindIndex(p => p == originColor); } } }

颜色原型实现:

  颜色原型提供了克隆的接口

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PrototypePattern.Color
{
  //抽象颜色原型
public abstract class ColorPrototype { public abstract ColorPrototype Clone(); } }

具体颜色类实现:

  具体颜色对象封装了颜色分量,通过克隆产生具体颜色对象(这里是浅复制,深复制见引用博客网址)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
namespace PrototypePattern.Color
{
  //具体颜色原型
public class ConcreteColorPrototype:ColorPrototype { private int _red, _green, _blue; public int Red { get { return _red; } } public int Green { get { return _green; } } public int Blue { get { return _blue; } } public ConcreteColorPrototype(int red, int green, int blue) { this._red = red; this._green = green; this._blue = blue; } public override ColorPrototype Clone() { return this.MemberwiseClone() as ColorPrototype; } } }

Winform实现:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using PrototypePattern.Draw;

namespace PrototypePattern
{
    public partial class Form1 : Form
    {
        Palette p;
        DrawBoard db;
        bool isDraw = false;
        Point p_s;//画图起始点
        public Form1()
        {
            InitializeComponent();
       //设置调色板,并绘制在窗口上
            p = new Palette(ref pb_palette);
            p.InitializePalette("Colors.xml");
            p.Draw();
       //初始化画板
            db = new DrawBoard(ref pb_board, ref p);
         }

        private void pb_palette_MouseClick(object sender, MouseEventArgs e)
        {
            p.SelectColor(new Point(e.X, e.Y));
        }

        private void pb_board_MouseDown(object sender, MouseEventArgs e)
        {
            isDraw = true;
            p_s = new Point(e.X, e.Y);
        }

        private void pb_board_MouseMove(object sender, MouseEventArgs e)
        {
            if(isDraw)
                db.DrawLine(p_s, new Point(e.X, e.Y));
        }

        private void pb_board_MouseUp(object sender, MouseEventArgs e)
        {
            if (isDraw)
            {
                db.DrawLine(p_s, new Point(e.X, e.Y));
                isDraw = false;
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

       

    }
}

Colors.xml结构:

<?xml version="1.0" encoding="utf-8" ?>
<Colors>
  <width>
    32
  </width>
  <height>
    32
  </height>
  <color name="red">
    <r>255</r>
    <g>0</g>
    <b>0</b>
  </color>
  <color name="green">
    <r>0</r>
    <g>255</g>
    <b>0</b>
  </color>
  <color name="blue">
    <r>0</r>
    <g>0</g>
    <b>255</b>
  </color>
  <color name="purple">
    <r>108</r>
    <g>51</g>
    <b>101</b>
  </color>
  <color name="orange">
    <r>255</r>
    <g>160</g>
    <b>66</b>
  </color>
  <color name="black">
    <r>0</r>
    <g>0</g>
    <b>0</b>
  </color>
</Colors>

实现效果:

 

原型模式参考网址:http://terrylee.cnblogs.com/archive/2006/01/16/317896.html

posted on 2012-08-17 10:09  Gates.Li  阅读(422)  评论(6编辑  收藏  举报

导航