創建型模式(Creational Pattern)的主要特點是將對象的創建與使用分離,根據對象的創建與組合方式的不同,創建型模式可分為單例(Singleton)模式、原型(Prototype)模式、工廠方法(Factory Method)模式、抽象工廠(Abstract Factory)模式和建造者(Builder)模式 5 種。
本實驗的主要目的如下。
⒈了解 5 種“創建型模式”的定義、特點和工作原理。
⒉理解 5 種“創建型模式”的結構、實現和應用場景。
⒊學會應用 5 種“創建型模式”進行軟件開發。
創建型模式隱藏了對象的創建細節,對象的創建由相關的工廠來完成,使用者不需要關注對象的創建細節,這樣可以降低系統的耦合度。創建型模式共 5 種,它們分別是單例模式、原型模式、工廠方法模式、抽象工廠模式和建造者模式,其工作原理在各自的教程中也都有詳細的介紹,每種模式的實驗大概要花 2 個學時,大家可以根據實驗計劃來選做若干個實驗,下面以工廠方法模式為例,介紹其實驗過程。
工廠方法模式(Factory Method Pattern),也叫虛擬構造器(Virtual Constructor)模式或者多態工廠(Polymorphic Factory)模式。
在工廠方法模式中,工廠父類負責定義創建產品對象的公共接口,而工廠子類則負責生成具體的產品對象,這樣做的目的是將產品類的實例化操作延遲到工廠子類中完成。其結構圖如圖 1 所示。
圖1 工廠方法模式的類圖
工廠方法模式包含如下角色。
? 抽象工廠(Abstract Factory):提供了創建產品的接口,調用者通過它訪問具體工廠的工廠方法 newProduct() 來創建產品。
? 具體工廠(ConcreteFactory):主要是實現抽象工廠中的抽象方法,完成具體產品的創建。
? 抽象產品(Product):定義了產品的規范,描述了產品的主要特性和功能。
? 具體產品(ConcreteProduct):實現了抽象產品角色所定義的接口,由具體工廠來創建,它同具體工廠之間一一對應。
工廠方法模式的特點是當系統擴展需要添加新的產品對象時,僅僅需要添加一個具體產品對象以及一個具體工廠對象,原有工廠對象不需要進行任何修改,也不需要修改客戶端,很好地符合了“開閉原則”。
⒈ 用工廠方法模式設計一個電動自行車工廠的模擬程序。
要求:要為每種品牌的電動自行車提供一個子工廠,如愛瑪工廠專門負責生產愛瑪(Aima)牌電動自行車,雅迪工廠專門負責生產雅迪(Yadea)牌電動自行車。如果今后需要生產臺鈴(Tailg)牌電動自行車,只需要增加一個新的臺鈴電動自行車工廠即可,無須修改原有代碼,使得整個系統具有更強的靈活性和可擴展性。(點此下載程序運行后所要顯示的圖片)。
⒉按照以上要求設計類圖和編寫 Java 源程序。
所設計的實驗程序要滿足以下兩點。
⒈體現“工廠方法模式”的工作原理。
⒉符合面向對象中的“開閉原則”。
⒈用 UML 設計“電動自行車工廠模擬程序”的結構圖。“電動自行車工廠模擬程序”的結構圖如圖 2 所示。
圖2 電動自行車工廠模擬程序的結構圖
⒉根據結構圖寫出“電動自行車工廠模擬程序”的源代碼。
① 電動自行車工廠模擬程序的源代碼如下。
package FactoryMethod;
import java.awt.*;
import javax.swing.*;
public class BicycleFactoryTest
{
public static void main(String[] args)
{
try
{
Bicycle a;
BicycleFactory bf;
bf=(BicycleFactory) ReadXML.getObject();
a=bf.produce();
a.show();
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
}
}
//抽象產品:自行車
interface Bicycle
{
public void show();
}
//具體產品:愛瑪自行車
class AimaBicycle implements Bicycle
{
JScrollPane sp;
JFrame jf=new JFrame("工廠方法模式測試");
public AimaBicycle()
{
JPanel p1=new JPanel();
p1.setLayout(new GridLayout(1,1));
p1.setBorder(BorderFactory.createTitledBorder("愛瑪自行車"));
JLabel l1=new JLabel(new ImageIcon("src/FactoryMethod/AIMABicycle.jpg"));
p1.add(l1);
sp=new JScrollPane(p1);
Container contentPane=jf.getContentPane();
contentPane.add(sp,BorderLayout.CENTER);
jf.pack();
jf.setVisible(false);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //用戶點擊窗口關閉
}
public void show()
{
jf.setVisible(true);
}
}
//具體產品:雅迪自行車
class YadeaBicycle implements Bicycle
{
JScrollPane sp;
JFrame jf=new JFrame("工廠方法模式測試");
public YadeaBicycle()
{
JPanel p1=new JPanel();
p1.setLayout(new GridLayout(1,1));
p1.setBorder(BorderFactory.createTitledBorder("雅迪自行車"));
JLabel l1=new JLabel(new ImageIcon("src/FactoryMethod/YadeaBicycle.jpg"));
p1.add(l1);
Container contentPane=jf.getContentPane();
sp=new JScrollPane(p1);
contentPane.add(sp, BorderLayout.CENTER);
jf.pack();
jf.setVisible(false);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //用戶點擊窗口關閉
}
public void show()
{
jf.setVisible(true);
}
}
//抽象工廠:自行車工廠
interface BicycleFactory
{
public Bicycle produce();
}
//具體工廠:愛瑪工廠
class AimaFactory implements BicycleFactory
{
public Bicycle produce()
{
System.out.println("愛瑪自行車生產了!");
return new AimaBicycle();
}
}
//具體工廠:雅迪工廠
class YadeaFactory implements BicycleFactory
{
public Bicycle produce()
{
System.out.println("雅迪自行車生產了!");
return new YadeaBicycle();
}
}
② 對象生成器的源代碼如下。
package FactoryMethod;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import java.io.*;
class ReadXML
{
public static Object getObject()
{
try
{
DocumentBuilderFactory dFactory=DocumentBuilderFactory.newInstance();
DocumentBuilder builder=dFactory.newDocumentBuilder();
Document doc;
doc=builder.parse(new File("src/FactoryMethod/config.xml"));
NodeList nl=doc.getElementsByTagName("className");
Node classNode=nl.item(0).getFirstChild();
String cName="FactoryMethod."+classNode.getNodeValue();
System.out.println("新類名:"+cName);
Class c=Class.forName(cName);
Object obj=c.newInstance();
return obj;
}
catch(Exception e)
{
e.printStackTrace();
return null;
}
}
}
③XML 配置文件的代碼如下。
<?xml version="1.0" encoding="UTF-8"?>
<config>
<className>AimaFactory</className>
</config>
⒊上機測試程序,寫出運行結果。
“電動自行車工廠模擬程序”的運行結果如圖 3 所示。
圖3 電動自行車工廠模擬程序的運行結果
⒋按同樣的步驟設計其他“創建型模式”的程序實例。
⒌寫出實驗心得。