java实现简单工厂模式

文章目录

  • java实现简单工厂模式
  • 更新2019.10.11

java实现简单工厂模式

--------记录人生第一次博客

ps: 最近在学习设计模式,老师给了实验要求完成,本来随便做完后就准备去干别的事情了,但是看到大佬写的实验后整个人的兴趣就被调动起来了,一番请教后写出比自己原先更好的代码后就有了写博客记录的欲望。

实验要求:1、有如下场景:现有一绘图工具,能够支持圆形、三角形、正方形等的绘图,每个图形都有绘图和擦除两个方法,请结合简单工厂模式实现该工具。

写代码最好先画画图理清楚思路再开始写。

思路:(ps:每个类都是单独的!)

  1. 创建窗口类MyFrame,继承JFrame类,然后在MyFrame类构造方法中完成初始化。
public class MyFrame extends JFrame{
	public MyFrame() {
		this.setTitle("mydemo");
		this.setSize(800, 400);//窗口类宽800px,高400px
		this.setVisible(true);//窗口是否开启可视化
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置关闭按钮关闭进程
	}
}
  1. 创建面板类MyPanel,继承JPanel类。再创建创建一个Demo类给出主函数main方法,回到MyFrame类。

  2. 在MyFrame类中,创建私有的MyPanel,创建6个JButton按钮,分别是:画圆,删圆,画矩形,删矩形,画三角形,删三角形。 `

public class MyFrame extends JFrame{
	private MyPanel panel = new MyPanel();
	private JButton c1 = new JButton("画圆");
	private JButton c2 = new JButton("删圆");
	private JButton r1 = new JButton("画矩形");
	private JButton r2 = new JButton("删矩形");
	private JButton t1 = new JButton("画三角形");
	private JButton t2 = new JButton("删三角形");
	public MyFrame() {
		this.setTitle("mydemo");
		this.setSize(800, 400);//窗口类宽800px,高400px
		this.setVisible(true);//窗口是否开启可视化
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置关闭按钮关闭进程
		
		c1.setBounds(10, 10, 100, 30);//x轴10px,y轴10px开始,按钮宽100px,高30px
		c2.setBounds(120, 10, 100, 30);
		
		r1.setBounds(230, 10, 100, 30);
		r2.setBounds(340, 10, 100, 30);
		
		t1.setBounds(450, 10, 100, 30);
		t2.setBounds(560, 10, 100, 30);
		
		this.add(c1);
		this.add(c2);
		this.add(r1);
		this.add(r2);
		this.add(t1);
		this.add(t2);
		add(panel);
	}
}

运行一下看看效果:

public class Demo {
	public static void main(String[] args) {
		MyFrame f=new MyFrame();
	}
}

java实现简单工厂模式_第1张图片

  1. 在面板类里画出圆形,矩形,三角形
public class MyPanel extends JPanel{
	public void paint(Graphics g) {//自动执行的函数
		g.drawOval(100,150,150,150);//画圆
		g.drawRect(300, 150, 150, 150);//画矩形
		drawTriangle(g, 500,300,600,150,700,300);//画三角形
	}
	//画三角形,将三个点连起来
	public void drawTriangle(Graphics g,int x1,int y1,int x2,int y2,int x3,int y3)    
	{     	    
	  Polygon filledPolygon=new Polygon();     
	  filledPolygon.addPoint(x1,y1);     
	  filledPolygon.addPoint(x2,y2);     
	  filledPolygon.addPoint(x3,y3);        
	  g.drawPolygon(filledPolygon);     
	    
	} 
}

java实现简单工厂模式_第2张图片

  1. 绑定JButton的触发事件,MyFrame继承ActionListener接口,实现actionPerformed(ActionEvent e)方法,这时候问题就出来了,MyPanel类的paint方法是自动执行的,怎么让它特定执行呢?所以将需要创建圆形类,矩形类,三角形类让方法能够根据各自特点用if判断执行。
public class Circle {//圆形
	int x,y;
	int width,height;
	
	public Circle(int x,int y,int width,int height) {//给出起始点,宽高
		super();
		this.x = x;
		this.y = y;
		this.width = width;
		this.height = height;
	}
	public int getX() {
		return x;
	}
	public void setX(int x) {
		this.x = x;
	}
	public int getY() {
		return y;
	}
	public void setY(int y) {
		this.y = y;
	}
	public int getWidth() {
		return width;
	}
	public void setWidth(int width) {
		this.width = width;
	}
	public int getHeight() {
		return height;
	}
	public void setHeight(int height) {
		this.height = height;
	}
}
public class Rect {//矩形
	int x,y,width,height;
 	public Rect(int x,int y,int width, int height) {
 		super();
 		this.x=x;
 		this.y=y;
 		this.width=width;
 		this.height=height;
 	}
	public int getX() {
		return x;
	}
	public void setX(int x) {
		this.x = x;
	}
	public int getY() {
		return y;
	}
	public void setY(int y) {
		this.y = y;
	}
	public int getWidth() {
		return width;
	}
	public void setWidth(int width) {
		this.width = width;
	}
	public int getHeight() {
		return height;
	}
	public void setHeight(int height) {
		this.height = height;
	}
}
public class Triangle {//三角形
	int x1,y1;//给出三个坐标点
	int x2,y2;
	int x3,y3;
	public Triangle(int x1,int y1,int x2,int y2,int x3,int y3) {
		super();
		this.x1=x1;
		this.y1=y1;
		this.x2=x2;
		this.y2=y2;
		this.x3=x3;
		this.y3=y3;
	}
	public int getX1() {
		return x1;
	}
	public void setX1(int x1) {
		this.x1 = x1;
	}
	public int getY1() {
		return y1;
	}
	public void setY1(int y1) {
		this.y1 = y1;
	}
	public int getX2() {
		return x2;
	}
	public void setX2(int x2) {
		this.x2 = x2;
	}
	public int getY2() {
		return y2;
	}
	public void setY2(int y2) {
		this.y2 = y2;
	}
	public int getX3() {
		return x3;
	}
	public void setX3(int x3) {
		this.x3 = x3;
	}
	public int getY3() {
		return y3;
	}
	public void setY3(int y3) {
		this.y3 = y3;
	}	
}
  1. 在MyPanel类创建这三个类,给出get和set方法,根据这三个类是否为空来判断是否执行相应语句。
public class MyPanel extends JPanel{
	
	private Circle circle = null;
	private Rect rect =null;
	private Triangle triangle=null;
	
	public Circle getCircle() {
		return circle;
	}
	public void setCircle(Circle circle) {
		this.circle = circle;
	}
	public Rect getRect() {
		return rect;
	}
	public void setRect(Rect rect) {
		this.rect = rect;
	}
	public Triangle getTriangle() {
		return triangle;
	}
	public void setTriangle(Triangle triangle) {
		this.triangle = triangle;
	}
	public void paint(Graphics g) {//通过get方法获得各个图形参数
		if(circle != null) g.drawOval(circle.getX(), circle.getY(), circle.getWidth(), circle.getHeight());
		
		if(rect != null) g.drawRect(rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight());
		
		if(triangle != null) drawTriangle(g,triangle.getX1(),triangle.getY1(),triangle.getX2(),triangle.getY2(),triangle.getX3(),triangle.getY3());
	}
	//画三角形,将三个点连起来
	public void drawTriangle(Graphics g,int x1,int y1,int x2,int y2,int x3,int y3)    
	{     	    
	  Polygon filledPolygon=new Polygon();     
	  filledPolygon.addPoint(x1,y1);     
	  filledPolygon.addPoint(x2,y2);     
	  filledPolygon.addPoint(x3,y3);        
	  g.drawPolygon(filledPolygon);     
	    
	} 
}

然后回到MyFrame类,创建三个类,并给出参数,完善actionPerformed(ActionEvent e)方法。

public class MyFrame extends JFrame implements ActionListener{
	private MyPanel panel = new MyPanel();
	private JButton c1 = new JButton("画圆");
	private JButton c2 = new JButton("删圆");
	private JButton r1 = new JButton("画矩形");
	private JButton r2 = new JButton("删矩形");
	private JButton t1 = new JButton("画三角形");
	private JButton t2 = new JButton("删三角形");
	private Circle circle = new Circle(100,150,150,150);
	private Rect rect = new Rect(300, 150, 150, 150);
	private Triangle triangle= new Triangle(500,300,600,150,700,300);
	public MyFrame() {
		this.setTitle("mydemo");
		this.setSize(800, 400);//窗口类宽800px,高400px
		this.setVisible(true);//窗口是否开启可视化
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置关闭按钮关闭进程
		
		//设定按钮位置以及宽高
		c1.setBounds(10, 10, 100, 30);//x轴10px,y轴10px开始,按钮宽100px,高30px
		c2.setBounds(120, 10, 100, 30);
		r1.setBounds(230, 10, 100, 30);
		r2.setBounds(340, 10, 100, 30);
		t1.setBounds(450, 10, 100, 30);
		t2.setBounds(560, 10, 100, 30);
		
		c1.addActionListener(this);//添加画画监听
		r1.addActionListener(this);
		t1.addActionListener(this);
		
		c2.addActionListener(this);//添加删除监听
		r2.addActionListener(this);
		t2.addActionListener(this);
			
		this.add(c1);
		this.add(c2);
		this.add(r1);
		this.add(r2);
		this.add(t1);
		this.add(t2);
		add(panel);
	}
	@Override
	public void actionPerformed(ActionEvent e) {
		if(e.getSource() == c1) {panel.setCircle(circle);repaint(); //repaint()方法清空内容}
		else if(e.getSource() == c2) {panel.setCircle(null);repaint();}
		else if(e.getSource() == r1) {panel.setRect(rect);repaint();}
		else if (e.getSource() == r2) {panel.setRect(null);repaint();}
		else if (e.getSource() == t1) {panel.setTriangle(triangle);repaint();}
		else if (e.getSource() == t2) {panel.setTriangle(null);repaint();}
		else {
			System.out.println("error");
		}
	}
}
  1. 运行demo类的主函数进行测试,测试成功后开始进行简单工厂模式,即创建自定义一个工厂类,把所有的new操作封装进去,让工厂来执行new操作。
public class Factory {
	public static Circle createCircle(int x,int y,int width,int height) {
		return new Circle(x, y, width, height);
	}
	
	public static Rect createRect(int x,int y,int width,int height) {
		return new Rect(x, y, width, height);
	}
	
	public static Triangle createTriangle(int x1,int y1,int x2,int y2,int x3,int y3) {
		return new Triangle(x1, y1, x2, y2, x3, y3);
	}
	public static JButton createJButton(String s) {
		return new JButton(s);
	}
	public static MyFrame createMyFrame() {
		return new MyFrame();
	}
	public static MyPanel createMyPanel() {
		return new MyPanel();
	}
}
  1. 最后一步就是把代码中的new操作全部改成调用工厂的方法帮你调用,例如:
	//在MyFrame类中的new操作,调用工厂类帮你创建
	private JButton c1 = Factory.createJButton("画圆");
	private JButton c2 = Factory.createJButton("删圆");
	private JButton r1 = Factory.createJButton("画矩形");
	private JButton r2 = Factory.createJButton("删矩形");
	private JButton t1 = Factory.createJButton("画三角形");
	private JButton t2 = Factory.createJButton("删三角形");
	private Circle circle = Factory.createCircle(100,150,150,150);
	private Rect rect = Factory.createRect(300, 150, 150, 150);
	private Triangle triangle = Factory.createTriangle(500,300,600,150,700,300);

//还有主函数创建的MyFrame f
MyFrame f = Factory.createMyFrame();

完成啦,<( ̄︶ ̄)>

代码其实还能更加简洁,但是懒得继续改了。

此处感谢大佬的帮助 https://blog.csdn.net/qq_39852560

如有不足,请各位大佬指正!

如果有别的思路也可以在评论区交流。

————————————————————分割线—————————————————

更新2019.10.11

有博主私信说简单工厂模式里的类可以抽象出父类。所以我把代码重构了一下。
更改部分:

  1. 将三角形类 Triangle 的成员变量 x1,y1,x2,y2,x3,y3及其set、get方法删除。
  2. 将三角形类,圆形类,矩形类抽象出父类 MyGraph。
  3. 将工厂类 Factory 的 createCircle(),createRect(),createTriangle()方法删除,添加了createMyGraph()方法。
  4. 修改了窗口类 MyFrame 成员变量从工厂类Factory获取方法 createMyGraph()。
  5. 修改了面板类 MyPanel 成员变量以及set、get方法,修改了画三角形的方法 drawTriangle()的参数

重构代码如下:

MyFrame类

public class MyFrame extends JFrame implements ActionListener {
    private MyPanel panel = new MyPanel();
    private JButton c1 = Factory.createJButton("画圆");
    private JButton c2 = Factory.createJButton("删圆");
    private JButton r1 = Factory.createJButton("画矩形");
    private JButton r2 = Factory.createJButton("删矩形");
    private JButton t1 = Factory.createJButton("画三角形");
    private JButton t2 = Factory.createJButton("删三角形");
    private MyGraph circle = Factory.createGraph("circle", 100, 150, 150, 150);
    private MyGraph rect = Factory.createGraph("rect",300, 150, 150, 150);
    private MyGraph triangle =  Factory.createGraph("triangle",500,150,150,150);

    public MyFrame() {
        this.setTitle("mydemo");
        this.setSize(800, 400);//窗口类宽800px,高400px
        this.setVisible(true);//窗口是否开启可视化
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置关闭按钮关闭进程

        //设定按钮位置以及宽高
        c1.setBounds(10, 10, 100, 30);//x轴10px,y轴10px开始,按钮宽100px,高30px
        c2.setBounds(120, 10, 100, 30);
        r1.setBounds(230, 10, 100, 30);
        r2.setBounds(340, 10, 100, 30);
        t1.setBounds(450, 10, 100, 30);
        t2.setBounds(560, 10, 100, 30);

        c1.addActionListener(this);//添加画画监听
        r1.addActionListener(this);
        t1.addActionListener(this);

        c2.addActionListener(this);//添加删除监听
        r2.addActionListener(this);
        t2.addActionListener(this);

        this.add(c1);
        this.add(c2);
        this.add(r1);
        this.add(r2);
        this.add(t1);
        this.add(t2);
        add(panel);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == c1) {
            panel.setCircle(circle);
            repaint();//repaint()方法清空内容
        }
        else if (e.getSource() == c2) {
            panel.setCircle(null);
            repaint();
        } else if (e.getSource() == r1) {
            panel.setRect(rect);
            repaint();
        } else if (e.getSource() == r2) {
            panel.setRect(null);
            repaint();
        } else if (e.getSource() == t1) {
            panel.setTriangle(triangle);
            repaint();
        } else if (e.getSource() == t2) {
            panel.setTriangle(null);
            repaint();
        } else {
            System.out.println("error");
        }
    }
}

MyPanel类

public class MyPanel extends JPanel {
    private MyGraph circle = null;
    private MyGraph rect =null;
    private MyGraph triangle=null;

    public MyGraph getCircle() {
        return circle;
    }

    public void setCircle(MyGraph circle) {
        this.circle = circle;
    }

    public MyGraph getRect() {
        return rect;
    }

    public void setRect(MyGraph rect) {
        this.rect = rect;
    }

    public MyGraph getTriangle() {
        return triangle;
    }

    public void setTriangle(MyGraph triangle) {
        this.triangle = triangle;
    }

    public void paint(Graphics g) {//通过get方法获得各个图形参数
        if(circle != null) 
        	g.drawOval(circle.getX(), circle.getY(), circle.getWidth(), circle.getHeight());

        if(rect != null) 
        	g.drawRect(rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight());

        if(triangle != null) 
        	drawTriangle(g,triangle.getX(),triangle.getY(),triangle.getWidth(), triangle.getHeight());
    }
    //画三角形,将三个点连起来
    public void drawTriangle(Graphics g,int x,int y,int width,int height)
    {
        Polygon filledPolygon=new Polygon();
        filledPolygon.addPoint(x,y); //起点
        filledPolygon.addPoint(width/2+x,y+height); //中间点
        filledPolygon.addPoint(x+width,y); //结束点
        g.drawPolygon(filledPolygon);//画三角形
    }
}

父类MyGraph,子类Circle,Rect,Triangle

public abstract class MyGraph {
    private int x,y;
    private int width,height;

    public MyGraph(){}

    public MyGraph(int x, int y, int width, int height) {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    public int getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }
}
public class Circle extends MyGraph{//圆形
    
    public Circle() {}

    public Circle(int x, int y, int width, int height) {
        super(x, y, width, height);
    }
}
public class Rect extends MyGraph{//矩形

    public Rect() {}

    public Rect(int x, int y, int width, int height) {super(x, y, width, height);}
}
public class Triangle extends MyGraph{//三角形

    public Triangle() {}

    public Triangle(int x, int y, int width, int height) {
        super(x, y, width, height);
    }
}

工厂类Factory

public class Factory {
    private static MyGraph myGraph = null;
    //通过参数确定图形
    public static MyGraph createGraph(String graphName,int startPointX,int startPointY,int width,int height){
        switch (graphName){
            case "circle":
            case "Circle":myGraph = new Circle(startPointX, startPointY, width, height);break;
            case "rect":
            case "Rect":myGraph = new Rect(startPointX, startPointY, width, height);break;
            case "triangle":
            case "Triangle": myGraph = new Triangle(startPointX, startPointY, width, height);break;
            default:myGraph = null;
        }
        return myGraph;
    }

    public static JButton createJButton(String buttonName) {
        return new JButton(buttonName);
    }
    public static MyFrame createMyFrame() {
        return new MyFrame();
    }
    public static MyPanel createMyPanel() {
        return new MyPanel();
    }
}

运行类Demo

public class Demo {
    public static void main(String[] args) {
        MyFrame f = Factory.createMyFrame();
    }
}

上面代码如果再继续深入考虑的话会发现,还有很多问题。

1.如果是五边形、六边形的话,父类 MyGraph 的 width 和 height 怎么搞?
2.多边形的话工厂类的参数怎么传?四个参数 x,y,width,height 可是直接把图形边数定死了!
3.使用工厂类返回想要的图形类,如果图形名字写错了或者不会写,那不是爆炸?

所以上面的代码只是提供学习使用,真正把它做成一个桌面应用还需要考虑很多的因素。

你可能感兴趣的:(设计模式)