一.何为工厂模式
工厂模式可以分为三类:
1)简单工厂模式(Simple Factory)
2)工厂方法模式(Factory Method)
3)抽象工厂模式(Abstract Factory)
这三种模式从上到下逐步抽象,并且更具一般性。
GOF在《设计模式》一书中将工厂模式分为两类:工厂方法模式(Factory Method)与抽象工厂模式(Abstract Factory)。
将简单工厂模式(Simple Factory)看为工厂方法模式的一种特例,两者归为一类。
区别
工厂方法模式:一个抽象产品类,可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类只能创建一个具体产品类的实例。
抽象工厂模式:
多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类可以创建多个具体产品类的实例。
区别:
工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。
工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。
两者皆可。
(以上转自http://blog.csdn.net/jason0539/article/details/23020989)
个人总结:
笔者一开始就是把这几个模式搞混了,通过阅读这篇博客才分清楚各自的区别,简而言之,区别这两种模式的要点就是抽象工厂与抽象产品的数目,若都为1,则是工厂方法模式,若大于1,则是抽象工厂模式。下述代码示例为工厂方法模式。同样也是用MVC架构来实现。
二.为何需要工厂模式
对于此问题,笔者的理解是,很多情况下,初始化工作是比较复杂的,将很多工作装入一个方法中,,是比较危险的,一个模块的食物很容易造成整个程序的错误,而通过使用工厂模式,能将创建实例的工作与使用实例的工作分开, 也就是说,让创建实例所需要的大量初始化工作从类的构造函数中分离出去。同时这种分离式很有意义的,打个很简单的比方,客户和生产商之间的关系。对客户来说,客户向生产商提出自己的要求,最后要获得成品,客户并不关注生产生是如何生产这种东西的,只关注结果。于此同时生厂商也并不关注客户为何会有这些要求,只需要生产客户所要求的东西便可以了。通过这种创建与使用的分离,就会将风险分散,以后如果需要修改,只要更改每段,不会再发生牵一动百的事情。
三.代码实例
Model模块(也就是产品部分)
接口Update:作用是通过接口回掉将更新消息传递给界面
public interface Update { public void update(String att); }
抽象产品数
public abstract class Num { public abstract int getNum(); public abstract String getAttribute(); }
具体产品类奇数
public class OddNum extends Num{ private int num; private String att; private Update upt; public OddNum(int i,Update up) { num=i; att=new String("是一个奇数"); upt=up; upt.update(att); } public int getNum() { return num; } public String getAttribute() { return att; } }
具体产品类偶数
public class EvenNum extends Num{ private int num; private String att; private Update upt; public EvenNum(int i,Update up) { num=i; att=new String("是一个偶数"); upt=up; upt.update(att); } public int getNum() { return num; } public String getAttribute() { return att; } }
抽象工厂类
public abstract class Factory { public abstract Num CreateNum(int i,Update up); }
具体工厂类奇数工厂
public class OddFactory extends Factory { public Num CreateNum(int i,Update up) { return new OddNum(i,up); } }
具体工厂类偶数工厂
public class EvenFactory extends Factory{ public Num CreateNum(int i,Update up) { return new EvenNum(i,up); } }
Controller模块(可进行创建num于选择视图等操作)
import javax.swing.JFrame; public class FacCon { private Num NUM; private NumView1 VIEW1; private NumView2 VIEW2; private EvenFactory efac; private OddFactory ofac; private int mode;//视图模式选择 public FacCon() { efac=new EvenFactory(); ofac=new OddFactory(); } public void setMode(int i)//设置视图模式,1为界面,2为控制台 { mode=i; } public void CreateNum(int num) { if(num%2==0) { if(mode==1) NUM=efac.CreateNum(num,VIEW1); else NUM=efac.CreateNum(num,VIEW2); } else { if(mode==1) NUM=ofac.CreateNum(num,VIEW1); else NUM=ofac.CreateNum(num,VIEW2); } } public int getNum() { return NUM.getNum(); } public String getAttribute() { return NUM.getAttribute(); } public void Judge()//由于工厂已经选择好建立奇偶对象,所以不需进行多余的判别 { } public void ShowView() { switch(mode){ case 1: { VIEW1=new NumView1(this); VIEW1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); VIEW1.setSize(450,120); VIEW1.setVisible(true); break; } case 2: { VIEW2=new NumView2(this); VIEW2.show(); break; } default :System.out.println("设置视图模式错误"); } } }
View模块
界面模式
import java.awt.Container;
import javax.swing.JFrame;
import java.awt.FlowLayout;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.*;
public class NumView1 extends JFrame implements Update {
/**
*
*/
private static final long serialVersionUID = 1L;
private FacCon CONTROL;
private boolean HasChange=false;
private String Att;
public NumView1(FacCon Con)
{
super("奇偶判断");
CONTROL=Con;
Container c=getContentPane();//创建面板
c.setLayout(new FlowLayout());
JTextField DisNum=new JTextField("数字:",8);
DisNum.setEditable(false);
JTextField Num=new JTextField(8);//用于输入数字
Num.setEditable(true);
JButton Judge=new JButton("判断");
JTextField Display=new JTextField(8); //显示判断结果
Display.setEditable(false);
c.add(DisNum);
c.add(Num);
c.add(Judge);
c.add(Display);
Judge.addMouseListener(new MouseListener(){
public void mouseClicked(MouseEvent e)
{
String _num=Num.getText();
CONTROL.CreateNum(Integer.parseInt(_num));
CONTROL.Judge();
if(HasChange==true)
{
Display.setText(Att);
HasChange=false;
}
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
});
}
public void update(String att)
{
HasChange=true;
Att=att;
}
}
import java.awt.Container;
import javax.swing.JFrame;
import java.awt.FlowLayout;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.*;
public class NumView1 extends JFrame implements Update {
/**
*
*/
private static final long serialVersionUID = 1L;
private FacCon CONTROL;
private boolean HasChange=false;
private String Att;
public NumView1(FacCon Con)
{
super("奇偶判断");
CONTROL=Con;
Container c=getContentPane();//创建面板
c.setLayout(new FlowLayout());
JTextField DisNum=new JTextField("数字:",8);
DisNum.setEditable(false);
JTextField Num=new JTextField(8);//用于输入数字
Num.setEditable(true);
JButton Judge=new JButton("判断");
JTextField Display=new JTextField(8); //显示判断结果
Display.setEditable(false);
c.add(DisNum);
c.add(Num);
c.add(Judge);
c.add(Display);
Judge.addMouseListener(new MouseListener(){
public void mouseClicked(MouseEvent e)
{
String _num=Num.getText();
CONTROL.CreateNum(Integer.parseInt(_num));
CONTROL.Judge();
if(HasChange==true)
{
Display.setText(Att);
HasChange=false;
}
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
});
}
public void update(String att)
{
HasChange=true;
Att=att;
}
}
控制台模式
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class NumView2 implements Update{
private FacCon CONTROL;
private boolean HasChange=false;
private String Att;
public NumView2(FacCon Con) {
CONTROL=Con;
}
public void show(){
BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
String _num;
try
{
do{
_num=in.readLine();
if(Integer.parseInt(_num)!=-1)
{
CONTROL.CreateNum(Integer.parseInt(_num));//对对象进行相关处理
CONTROL.Judge();// 判断并设置属性
if(HasChange==true)
{
System.out.println(CONTROL.getAttribute());
HasChange=false;
}
}
}while(Integer.parseInt(_num)!=-1);
System.out.println("结束");
}
catch(IOException e)
{
System.out.println(e.getMessage());
e.printStackTrace();
}
}
public void update(String att)
{
HasChange=true;
Att=att;
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class NumView2 implements Update{
private FacCon CONTROL;
private boolean HasChange=false;
private String Att;
public NumView2(FacCon Con) {
CONTROL=Con;
}
public void show(){
BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
String _num;
try
{
do{
_num=in.readLine();
if(Integer.parseInt(_num)!=-1)
{
CONTROL.CreateNum(Integer.parseInt(_num));//对对象进行相关处理
CONTROL.Judge();// 判断并设置属性
if(HasChange==true)
{
System.out.println(CONTROL.getAttribute());
HasChange=false;
}
}
}while(Integer.parseInt(_num)!=-1);
System.out.println("结束");
}
catch(IOException e)
{
System.out.println(e.getMessage());
e.printStackTrace();
}
}
public void update(String att)
{
HasChange=true;
Att=att;
}
}
最后是测试模块
public class MvcAndFac {
public static void main(String[] args) {
FacCon Controller=new FacCon();//获取唯一实例
Controller.setMode(1);
Controller.ShowView();
}
}
public class MvcAndFac {
public static void main(String[] args) {
FacCon Controller=new FacCon();//获取唯一实例
Controller.setMode(1);
Controller.ShowView();
}
}
四.运行结果
视图模式
控制台
五.总结
首先是要在MVC架构下和工厂模式相结合,然后主要的就是分辨几种工厂模式的差异,通过看一些资深猿的博客弄明白了其中的差别,后面就是代码的实现了。最后就是MVC架构的设计,关于对MVC的理解笔者会在后面的博客再探讨。比较粗糙,如果有什么好的建议与发现什么错误的地方,请在评论区留言谢谢。