在上一篇博客中我们使用了工厂模式来设计一个网上车辆交易系统。在那个样例中仅仅有汽车这一种单一类型的商品。那么,假设有多种类型的商品。还能用工厂方法模式吗?举个样例,如今有个网上服装买卖系统。有三种服装---鞋、套装和衬衫,当中又分为男鞋女鞋、男套装和女套装、男衬衫和女衬衫。即例如以下商品:
依照上节中说到的工厂方法模式,应该这样设计。使用三个工厂来创建三个对象:
这样做也能实现。可是工厂类有点多吧,并且在client中将会有非常多的条件语句,有没有什么更好的办法呢?我们在分析看看。商品有三种,性别相应着男、女,那么我们为什么不从还有一个角度来思考问题,不再建立生产shoes、shirt和suit的工厂。而是建立生产男人的衣服工厂ManCloseFactory和生产女人衣服的工厂WomanCLoseFactory。例如以下设计:
类图设计好了。如今仅仅须要两个工厂就能搞定了,那么编代码试试吧:
shirt接口:
public interface Shirt { public String getInfo(); }
suit接口:
public interface Suit { public String getInfo(); }
shoes接口:
public interface Shoes { public String getInfo(); }
ManShirt类:
public class ManShirt implements Shirt { @Override public String getInfo() { // TODO Auto-generated method stub String info = "男 衬衫"; return info; } }
WomanShirt类:
public class WomanShirt implements Shirt { @Override public String getInfo() { // TODO Auto-generated method stub String info = "女 衬衫"; return info; } }
ManSuit类:
public class ManSuit implements Suit { @Override public String getInfo() { // TODO Auto-generated method stub String info = "男 套装"; return info; } }
WomanSuit类:
public class WomanSuit implements Suit { @Override public String getInfo() { // TODO Auto-generated method stub String info = "女 套装"; return info; } }
ManShoes类:
public class ManShoes implements Shoes { @Override public String getInfo() { // TODO Auto-generated method stub String info = "男 鞋"; return info; } }
WomanShoes类:
public class WomanShoes implements Shoes { @Override public String getInfo() { // TODO Auto-generated method stub String info = "女 鞋"; return info; } }
工厂类的基类:
public abstract class CloseFactory { public static final String MAN = "男"; public static final String WOMAN = "女"; public abstract Shoes getShoes(); public abstract Suit getSuit(); public abstract Shirt getShirt(); public static CloseFactory getCloseFactory(String Sex){ CloseFactory CF = null; if(Sex.equals(MAN)){ CF = new ManCloseFactory(); }else if(Sex.equals(WOMAN)){ CF = new WomanCloseFactory(); } return CF; } }
男服生产工厂,ManCloseFactory:
public class ManCloseFactory extends CloseFactory { @Override public Shoes getShoes() { // TODO Auto-generated method stub return new ManShoes(); } @Override public Suit getSuit() { // TODO Auto-generated method stub return new ManSuit(); } @Override public Shirt getShirt() { // TODO Auto-generated method stub return new ManShirt(); } }
女服生产工厂,WomanCloseFactory:
public class WomanCloseFactory extends CloseFactory { @Override public Shoes getShoes() { // TODO Auto-generated method stub return new WomanShoes(); } @Override public Suit getSuit() { // TODO Auto-generated method stub return new WomanSuit(); } @Override public Shirt getShirt() { // TODO Auto-generated method stub return new WomanShirt(); } }
client:
import java.awt.Color; import java.awt.Dimension; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextArea; public class clientGUI extends JFrame implements ActionListener{ private String SHOES = "鞋"; private String SHIRT = "衬衫"; private String SUIT = "套装"; private String MAN = "男"; private String WOMAN = "女"; private JLabel labelShowSex; private JLabel labelShowType; private JTextArea textShowInfo; private JComboBox ChoiceSex; private JComboBox ChoiceType; private JButton BtnOK; private JButton BtnExit; private JPanel panelNorth; private JPanel panelCenter; private JPanel panelSouth; public void initComponents(){ labelShowSex = new JLabel("请选择性别:"); labelShowType = new JLabel("请选择服饰:"); textShowInfo = new JTextArea(); textShowInfo = new JTextArea(); textShowInfo.setColumns(20); textShowInfo.setRows(100); textShowInfo.setBackground(Color.PINK); ChoiceSex = new JComboBox(); ChoiceSex.addItem(MAN); ChoiceSex.addItem(WOMAN); ChoiceType = new JComboBox(); ChoiceType.addItem(SHOES); ChoiceType.addItem(SHIRT); ChoiceType.addItem(SUIT); BtnOK = new JButton("OK"); BtnOK.addActionListener(this); BtnExit = new JButton("EXIT"); BtnExit.addActionListener(this); panelNorth = new JPanel(); panelCenter = new JPanel(); panelSouth = new JPanel(); } public void panelAddComponenets(){ panelNorth.add(labelShowSex); panelNorth.add(ChoiceSex); panelNorth.add(labelShowType); panelNorth.add(ChoiceType); panelCenter.add(textShowInfo); panelSouth.add(BtnOK); panelSouth.add(BtnExit); } public void mainFrameAddPanel(){ this.add("North", panelNorth); this.add("Center", panelCenter); this.add("South", panelSouth); } public void mianFramSet(){ Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); this.setLocation((d.width - this.getSize().width)/2, (d.height - this.getSize().height)/2); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setSize(300, 200); this.setVisible(true); } public clientGUI(){ initComponents(); panelAddComponenets(); mainFrameAddPanel(); mianFramSet(); } @Override public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub if(e.getSource() == BtnOK){ String Sex = ChoiceSex.getSelectedItem().toString(); String Type = ChoiceType.getSelectedItem().toString(); CloseFactory cf = CloseFactory.getCloseFactory(Sex);//依据性别调用对应的工厂 if(Type.equals(SHIRT)){//依据类型生产对应的产品 Shirt s = cf.getShirt(); String info = s.getInfo(); textShowInfo.setText(info); }else if(Type.equals(SHOES)){ Shoes s = cf.getShoes(); String info = s.getInfo(); textShowInfo.setText(info); }else if(Type.equals(SUIT)){ Suit s = cf.getSuit(); String info = s.getInfo(); textShowInfo.setText(info); } } if(e.getSource() == BtnExit){ System.exit(0); } } }
測试:
public class mian { public static void main(String[] args) { // TODO Auto-generated method stub clientGUI cGUI = new clientGUI(); } }
这样设计是不是好多了。!
!
总结一下,抽象工厂模式应用在产品类别不唯一的情况,而工厂模式应用在产品类别单一的情况。再画一下抽象工厂模式的设计图:
上节中说到。工厂方法符合开闭原则,可是抽象工厂方法仅仅是部分的符合开闭原则,举个样例: