绘图小工具-工厂模式设计

Posted zjdiem

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了绘图小工具-工厂模式设计相关的知识,希望对你有一定的参考价值。

  工厂模式:不提供一个统一的工厂类来创建所有的对象,而是针对不同的对象提供不同的工厂,每个对象都有一个与之对应的工厂 。

  绘图小工具类图:

技术图片

使用工厂模式降低了类之间的耦合,可以方便地增删绘图的功能。

功能包括:画方、画圆、画折线、画曲线、绘制中和绘制后有颜色差异。

主框架:

技术图片
import JavaDraw.factory.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;

public class DrawJFrame extends JFrame implements ActionListener
{
    protected JComboBox<Integer> combox_size;//线条宽度组合框
    private JRadioButton radio[];              //单选按钮数组
    private DrawCanvas canvas;
    private String[] s;
    public DrawJFrame()
    {
        super("画图小工具!!!");
        this.setSize(1200,900);
        this.setLocationRelativeTo(null);
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        JToolBar toolbar=new JToolBar();     //工具栏,默认水平方向
        this.getContentPane().add(toolbar, "North");//工具栏添加到框架北

        JLabel lable=new JLabel("粗细");
        toolbar.add(lable);
        Integer sizes[]= {1,2,3,4,5,6,};    //画线大小
        this.combox_size= new JComboBox<>(sizes);
        this.combox_size.setMaximumSize(new Dimension(50, 30));
        this.combox_size.setEditable(true);  //设置组合框可编辑
        this.combox_size.addActionListener(this);
        toolbar.add(this.combox_size);

        toolbar.addSeparator(new Dimension(50, 30));
        s= new String[]{"直线", "矩形", "圆", "曲线","三角形"};       //单选按钮数组
        ButtonGroup bgroup=new ButtonGroup();
        this.radio=new JRadioButton[s.length];
        for(int i=0;i<s.length;i++)
        {
            this.radio[i]=new JRadioButton(s[i]);
            this.radio[i].addActionListener(this);
            bgroup.add(this.radio[i]);
            toolbar.add(this.radio[i]);
        }
        this.radio[0].setSelected(true);

        toolbar.addSeparator(new Dimension(50, 30));
        JButton color_button=new JButton("选择颜色");//颜色按钮
        JButton eraser_button=new JButton("橡皮檫");
        JButton new_button=new JButton("新建");
        color_button.addActionListener(this);
        eraser_button.addActionListener(this);
        new_button.addActionListener(this);
        toolbar.add(color_button);
        toolbar.addSeparator(new Dimension(60, 30));
        toolbar.add(eraser_button);
        toolbar.addSeparator(new Dimension(60, 30));
        toolbar.add(new_button);

        this.canvas=new DrawCanvas();
        canvas.setFactory(new LineFactory(canvas));
        this.getContentPane().add(canvas);
        this.setVisible(true);
    }
    @Override
    public void actionPerformed(ActionEvent ae)
    {
        if(ae.getSource() instanceof JComboBox<?>)
        {
            try
            {
                Object obj=this.combox_size.getSelectedItem();//获取输入值
                if(obj instanceof Integer)
                    canvas.size=((Integer)obj).intValue();
            }catch(NumberFormatException e)
            {
                JOptionPane.showMessageDialog(this, """+ this.combox_size.getSelectedItem() +"" 不能转换成整数,请重新输入!");
            }
        }
        if(ae.getActionCommand().equals("选择颜色"))
            canvas.color=JColorChooser.showDialog(this, "选择颜色", Color.BLACK);
        if(ae.getActionCommand().equals("新建"))
        {
            this.dispose();
            new DrawJFrame();

        }

        if(ae.getActionCommand().equals("橡皮檫"))
            canvas.setFactory(new EraserFactory(canvas));
        if(ae.getActionCommand().equals("直线"))
            canvas.setFactory(new LineFactory(canvas));
        if(ae.getActionCommand().equals("曲线"))
            canvas.setFactory(new CurveFactory(canvas));
        if(ae.getActionCommand().equals("矩形"))
            canvas.setFactory(new RectFactory(canvas));
        if(ae.getActionCommand().equals("圆"))
            canvas.setFactory(new OvalFactory(canvas));
        if(ae.getActionCommand().equals("三角形"))
            canvas.setFactory(new TriangleFactory(canvas));
    }
    public static void main(String[] args)
    {
        new DrawJFrame();
    }
}
DrawJFrame
技术图片
import JavaDraw.draw.Shape;
import JavaDraw.factory.ShapeFactory;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import java.util.List;
/**
 * Author: Z&J
 * E-mail: 320647879@qq.com
 * Time: 2018/12/2 16:11
 * 类描述-Description:
 * *
 */
public class DrawCanvas extends JComponent implements MouseMotionListener,MouseListener
{
    public int size;
    public Color color;
    public Point start,end;
    Shape shape;
    ShapeFactory sf;
    public List<JavaDraw.draw.Shape> list=new ArrayList<>();//容器类
    public DrawCanvas()
    {
        start=end=null;
        this.size=3;
        this.color=Color.black;
        this.addMouseMotionListener(this);
        this.addMouseListener(this);
    }
    @Override
    public void mousePressed(MouseEvent e)
    {
        sf.mousePressed(e);//调用ShapeFactory对象的mousePressed()方法,具体画什么由其子类实现
    }
    @Override
    public void mouseReleased(MouseEvent e)        //鼠标释放
    {
        sf.mouseReleased(e);
    }
    @Override
    public void mouseDragged(MouseEvent e)
    {
        sf.mouseDragged(e);
    }
    @Override
    public void mouseClicked(MouseEvent e){}        //单击鼠标
    @Override
    public void mouseEntered(MouseEvent e){}        //鼠标进入
    @Override
    public void mouseExited(MouseEvent e){}        //鼠标离开
    @Override
    public void mouseMoved(MouseEvent e){}        //移动鼠标,实现MouseMotionListener接口

    //通过函数传参的形式将shape和工厂对象传入canvas中
    public void setShape(JavaDraw.draw.Shape shape)
    {
        this.shape=shape;
    }
    public void setFactory(ShapeFactory sf)
    {
        this.sf=sf;
    }
    public void paint(Graphics g)
    {
        Graphics2D g2 = (Graphics2D)g;//Graphics2D才能设置画笔粗细。
        for(Shape d: list)
        {
            if(d!=null)
                d.draw(g2);//每次更新时,会清空画布,所以把list中的图形全部重绘一遍
        }
        if(shape!=null)
            shape.draw(g2);//绘图
    }
    public void update(Graphics g)
    {
        paint(g);
    }
}
DrawCanvas

图形抽象类:

技术图片
import java.awt.*;
/**
 * Author: Z&J
 * E-mail: 320647879@qq.com
 * Time: 2018/12/1 0:37
 * 类描述-Description:
 * *
 */
public abstract class Shape
{
    Point start,end;
    public Color color;
    public int size;
    public Shape(Point start, Point end, Color color,int size)
    {
        this.start = start;
        this.end = end;
        this.color = color;
        this.size = size;
    }
    public abstract void draw(Graphics2D g);
}
Shape

工厂抽象类:

技术图片
import JavaDraw.DrawCanvas;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
/**
 * Author:Z&J
 * E-mail: 320647879@qq.com
 * 版本:1.0
 * 创建日期:2019年09月20日 20:52
 * 类描述-Description:
 */
public abstract class ShapeFactory implements MouseListener, MouseMotionListener
{
    DrawCanvas canvas;
    public ShapeFactory(DrawCanvas canvas)
    {
        this.canvas = canvas;
    }
    @Override
    public abstract void mouseClicked(MouseEvent e);
    @Override
    public abstract void mouseEntered(MouseEvent e);
    @Override
    public abstract void mouseExited(MouseEvent e);
    @Override
    public abstract void mouseMoved(MouseEvent e);
    @Override
    public abstract void mousePressed(MouseEvent e);
    @Override
    public abstract void mouseDragged(MouseEvent e);
    @Override
    public abstract void mouseReleased(MouseEvent e);
    public abstract void setProduct(Color color);
}
ShapeFactory

图形类具体实现:

技术图片
import java.awt.*;
/**
 * Author:Z&J
 * E-mail: 320647879@qq.com
 * 版本:1.0
 * 创建日期:2019年09月17日 1:03
 * 类描述-Description:
 */
public class DrawLine extends Shape
{
    public DrawLine(Point start, Point end, Color color, int size)
    {
        super(start, end, color, size);
    }
    public void draw(Graphics2D g)
    {
        g.setStroke(new BasicStroke(size));//设置画笔粗细
        g.setColor(color);
        g.drawLine(start.x, start.y, end.x, end.y);
    }
}

public class DrawOval extends Shape
{
    public DrawOval(Point start, Point end, Color color, int size)
    {
        super(start, end, color, size);
    }
    @Override
    public void draw(Graphics2D g)
    {
        g.setStroke(new BasicStroke(size));//设置画笔粗细
        g.setColor(color);
        g.drawOval(start.x, start.y, Math.abs(end.x-start.x), Math.abs(end.y-start.y));
    }
}

public class DrawRect extends Shape
{
    public DrawRect(Point start, Point end, Color color, int size)
    {
        super(start, end, color, size);
    }
    @Override
    public void draw(Graphics2D g)
    {
        g.setStroke(new BasicStroke(size));//设置画笔粗细
        g.setColor(color);
        g.drawRect(start.x, start.y, Math.abs(end.x-start.x), Math.abs(end.y-start.y));
    }
}

public class DrawTriangle extends Shape
{
    public DrawTriangle(Point start, Point end, Color color, int size)
    {
        super(start, end, color, size);
    }
    @Override
    public void draw(Graphics2D g)
    {
        g.setStroke(new BasicStroke(size));
        g.setColor(color);
        g.drawLine(start.x,start.y,end.x,end.y);
        g.drawLine(start.x,start.y,2*start.x-end.x,end.y);
        g.drawLine(2*start.x-end.x,end.y,end.x,end.y);
    }
}
Draw

工厂类具体实现:

技术图片
package JavaDraw.factory;

import JavaDraw.DrawCanvas;
import JavaDraw.draw.DrawLine;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
/**
 * Author:Z&J
 * E-mail: 320647879@qq.com
 * 版本:5.0
 * 创建日期:2019年09月22日 12:00
 * 类描述-Description:工厂模式,每生产一个对象,先创建一个生产该对象的工厂。
 */
public class CurveFactory extends ShapeFactory
{
    DrawLine line;
    private List<DrawLine> temp=new ArrayList<>();
    public CurveFactory(DrawCanvas canvas)
    {
        super(canvas);
    }
    @Override
    public void mousePressed(MouseEvent e)
    {
        canvas.start=e.getPoint();
    }
    @Override
    public void mouseReleased(MouseEvent e)
    {
        canvas.end=e.getPoint();
        for (DrawLine curve:temp)
        {
            curve.color=canvas.color;
            canvas.setShape(curve);
        }
        canvas.repaint();
        temp.clear();
    }
    @Override
    public void mouseDragged(MouseEvent e)
    {
        canvas.end=e.getPoint();
        this.setProduct(Color.lightGray);//鼠标每次一移动,就生成一个新的产品
        canvas.repaint();//更新画布
        canvas.list.add(line);//由于是画曲线,所以需要把鼠标移动的时候产生的对象放到容器里去
        temp.add(line);//用一个临时容器保存画的点,在鼠标释放的时候好重绘该曲线
        canvas.start=canvas.end;//不断更新开始的点,才能画出曲线
    }
    @Override
    public void setProduct(Color color)//生产具体的产品
    {
        line=new DrawLine(canvas.start,canvas.end,color,canvas.size);
        canvas.setShape(line);//告诉画布要画什么图形
    }
}

public class EraserFactory extends ShapeFactory
{
    DrawLine eraser;
    public EraserFactory(DrawCanvas canvas)
    {
        super(canvas);
    }
    @Override
    public void mousePressed(MouseEvent e)
    {
        canvas.start=e.getPoint();
    }
    @Override
    public void mouseDragged(MouseEvent e)
    {
        canvas.end=e.getPoint();
        this.setProduct(canvas.getBackground());
        canvas.repaint();
        canvas.list.add(eraser);
        canvas.start=canvas.end;
    }
    @Override
    public void mouseReleased(MouseEvent e)
    {
        canvas.end=e.getPoint();
        canvas.repaint();
    }
    @Override
    public void setProduct(Color color)
    {
        eraser=new DrawLine(canvas.start,canvas.end, color,canvas.size);
        canvas.setShape(eraser);
    }
}

public class LineFactory extends ShapeFactory
{
    DrawLine line;
    public LineFactory(DrawCanvas canvas)
    {
        super(canvas);
    }
    @Override
    public void mousePressed(MouseEvent e)
    {
        canvas.start=e.getPoint();//记录点击鼠标的坐标
    }
    @Override
    public void mouseDragged(MouseEvent e)
    {
        canvas.end=e.getPoint();//鼠标移动的坐标
        this.setProduct(Color.lightGray);//鼠标移动时,画出具体的图形
        canvas.repaint();//canvas对象更新
    }
    @Override
    public void mouseReleased(MouseEvent e)
    {
        canvas.end=e.getPoint();//鼠标释放时的坐标
        this.setProduct(canvas.color);
        canvas.repaint();
        canvas.list.add(line);//将绘出的图形放到canvas的容器中
    }
    @Override
    public void setProduct(Color color)//生产具体的产品
    {
        line=new DrawLine(canvas.start,canvas.end, color,canvas.size);
        canvas.setShape(line);//将line对象传回canvas画布中绘图。
    }
}

public class OvalFactory extends ShapeFactory
{
    DrawOval oval;
    public OvalFactory(DrawCanvas canvas)
    {
        super(canvas);
    }
    @Override
    public void mouseDragged(MouseEvent e)
    {
        canvas.end=e.getPoint();
        this.setProduct(Color.lightGray);
        canvas.repaint();
    }
    @Override
    public void mouseReleased(MouseEvent e)
    {
        canvas.end=e.getPoint();
        this.setProduct(canvas.color);
        canvas.repaint();
        canvas.list.add(oval);
    }
    @Override
    public void setProduct(Color color)
    {
        oval=new DrawOval(canvas.start,canvas.end,color,canvas.size);
        canvas.setShape(oval);
    }
}

public class RectFactory extends ShapeFactory
{
    DrawRect rect;
    public RectFactory(DrawCanvas canvas)
    {
        super(canvas);
    }
    @Override
    public void mousePressed(MouseEvent e)
    {
        canvas.start=e.getPoint();
    }
    @Override
    public void mouseDragged(MouseEvent e)
    {
        canvas.end=e.getPoint();
        this.setProduct(Color.lightGray);
        canvas.repaint();
    }
    @Override
    public void mouseReleased(MouseEvent e)
    {
        canvas.end=e.getPoint();
        this.setProduct(canvas.color);
        canvas.repaint();
        canvas.list.add(rect);
    }
    @Override
    public void setProduct(Color color)
    {
        rect=new DrawRect(canvas.start,canvas.end,color,canvas.size);
        canvas.setShape(rect);
    }
}

public class TriangleFactory extends ShapeFactory
{
    DrawTriangle triangle;
    public TriangleFactory(DrawCanvas canvas)
    {
        super(canvas);
    }
    @Override
    public void mousePressed(MouseEvent e)
    {
        canvas.start=e.getPoint();//记录点击鼠标的坐标
    }
    @Override
    public void mouseDragged(MouseEvent e)
    {
        canvas.end=e.getPoint();//鼠标移动的坐标
        this.setProduct(Color.lightGray);//鼠标移动时,画出具体的图形
        canvas.repaint();//canvas对象更新
    }
    @Override
    public void mouseReleased(MouseEvent e)
    {
        canvas.end=e.getPoint();//鼠标释放时的坐标
        this.setProduct(canvas.color);
        canvas.repaint();
        canvas.list.add(triangle);//将绘出的图形放到canvas的容器中
    }
    @Override
    public void setProduct(Color color)//生产具体的产品
    {
        triangle=new DrawTriangle(canvas.start,canvas.end, color,canvas.size);
        canvas.setShape(triangle);
    }
}
Factory

以上是关于绘图小工具-工厂模式设计的主要内容,如果未能解决你的问题,请参考以下文章

设计模式---------------简单工厂模式

Java,设计模式,简单工厂。

设计模式——工厂模式

Delphi 设计模式:《HeadFirst设计模式》Delphi7代码---工厂模式之简单工厂

设计模式大冒险第三关:工厂模式,封装和解耦你的代码

java设计模式:工厂方法模式(Factory Method)