一、题目要求
- 结合实例,正确无误地绘制工厂方法模式、抽象工厂模式的模式结构图;
- 要求使用XML和Java反射机制来创建对象。
- 使用Java语言实现工厂方法模式、抽象工厂模式实例,代码运行正确无误。
二、实现过程及步骤
1.使用工厂方法模式设计一个程序用来读取各种不同类型的图片格式,针对每一种图片格式都设计一个图片读取器(ImageReader),例如GIF图片读取器(GifReader)用于读取GIF格式的图片、JPG图片读取器(JpgReader)用于读取JPG格式的图片。需充分考虑系统的灵活性和可扩展性。
(1)工厂方法模式设计:
首先设计一个抽象工厂接口ImageReader,里面有一个抽象方法Reader(),然后设计两个具体工厂GifReader,JpgReader去实现抽象工厂接口,其次再设计一个抽象产品类Picture,里面包含一个抽象Show( )方法,然后设计两个具体产品类GifPicture,JpgPicture去继承抽象产品类,最后设计一个XMLUilt类去获取.xml配置文件中的具体类名并返回一个实例对象。
(2)UML类图如下:
(3)运行结果如下:
(4)代码:
抽象工厂接口ImageReader
package factorypattern;
public interface ImageReader {
public abstract Picture Reader();
}
具体工厂GifReader,JpgReader
package factorypattern;
public class GifReader implements ImageReader {
@Override
public Picture Reader() {
return new GifPicture();
}
}
package factorypattern;
public class JpgReader implements ImageReader {
@Override
public Picture Reader() {
return new JpgPicture();
}
}
抽象产品类Picture
package factorypattern;
public abstract class Picture {
public abstract void Show();
}
具体产品类GifPicture,JpgPicture
package factorypattern;
public class GifPicture extends Picture{
@Override
public void Show() {
// TODO Auto-generated method stub
System.out.println("读取Gif格式的图片");
}
}
package factorypattern;
public class JpgPicture extends Picture{
@Override
public void Show() {
// TODO Auto-generated method stub
System.out.println("读取Jpg格式的图片");
}
}
XMLUilt类
package factorypattern;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
public class XMLUtil {
//该方法用于配置从XML配置文件中提取具体类名,并返回一个实例对象
public static Object getBean() {
try {
//创建DOM文档对象
DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dFactory.newDocumentBuilder();
Document doc;
doc = builder.parse(new File("src/factorypattern/config.xml"));
//获取包含类名的文本节点
NodeList n1 = doc.getElementsByTagName("className");
Node classNode = n1.item(0).getFirstChild();
String cName = classNode.getNodeValue();
Class c = Class.forName(cName);
Object obj = c.newInstance();
return obj;
}catch(Exception e) {
e.printStackTrace();
return null;
}
}
}
Text类
package factorypattern;
public class Text {
public static void main(String[] args) {
ImageReader imagereader;
Picture picture;
imagereader = (ImageReader)XMLUtil.getBean();
picture = imagereader.Reader();
picture.Show();
}
}
.xml配置文件
<?xml version="1.0"?>
<config>
<className>factorypattern.GifReader</className>
<className>factorypattern.JpgReader</className>
</config>
- 某软件公司欲开发一套界面皮肤库,可以对桌面软件进行界面美化。不同的皮肤将提供视觉效果不同的按钮、文本框、组合框等界面元素,其结构如下图所示:
该皮肤库需要具备良好的灵活性和可扩展性,用户可以自由选择不同的皮肤,开发人员可以在不修改既有代码的基础上增加新的皮肤。试使用抽象工厂模式设计该皮肤库,绘制类图并编程模拟实现。
(1)抽象工厂模式设计:
首先设计一个抽象工厂接口SkinFactory,里面有三个抽象方法createButton()、createComboBox()、createTextBox(),然后设计两个具体工厂类SpringSkinFactory和SummerSkinFactory分别实现抽象工厂接口里面的三个抽象方法,其次再设计三个抽象产品类AbstractButton、AbstractComboBox、AbstractTextBox,里面包含一个抽象action( )方法,然后对应三个不同的抽象产品类分别包括两个具体产品类,AbstractButton对应于BlueButton和GreenButton,以此类推。最后设计一个XMLUilt类去获取.xml配置文件中的具体类名并返回一个实例对象。
(2)UML类图如下:
(3)运行结果如下:
(4)代码:
抽象工厂接口SkinFactory
package abstractfactory;
public interface SkinFactory {
public AbstractButton createButton();
public AbstractComboBox createComboBox();
public AbstractTextBox createTextBox();
}
具体工厂类SpringSkinFactory和SummerSkinFactory(此处只列举SpringSkinFactory)
package abstractfactory;
public class SpringSkinFactory implements SkinFactory{
public AbstractButton createButton() {
System.out.println("Spring风格:生产绿色按钮");
return new GreenButton();
}
public AbstractTextBox createTextBox() {
System.out.println("Spring风格:生产绿色文本框");
return new GreenTextBox();
}
public AbstractComboBox createComboBox() {
System.out.println("Spring风格:生产绿色组合框");
return new GreenComboBox();
}
}
抽象产品类AbstractButton、AbstractComboBox、AbstractTextBox(此处只列举AbstractButton)
package abstractfactory;
public interface AbstractButton {
public void action();
}
具体产品类(此处只列举基于AbstractButton的两个具体产品类)
package abstractfactory;
public class BlueButton implements AbstractButton{
public void action() {
System.out.println("蓝色按钮生产成功");
}
}
package abstractfactory;
public class GreenButton implements AbstractButton{
public void action() {
System.out.println("绿色按钮生产成功");
}
}
XMLUilt类
package abstractfactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
public class XMLUtil {
//该方法用于配置从XML配置文件中提取具体类名,并返回一个实例对象
public static Object getBean() {
try {
//创建DOM文档对象
DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dFactory.newDocumentBuilder();
Document doc;
doc = builder.parse(new File("src/abstractfactory/config.xml"));
//获取包含类名的文本节点
NodeList n1 = doc.getElementsByTagName("className");
Node classNode = n1.item(0).getFirstChild();
String cName = classNode.getNodeValue();
Class c = Class.forName(cName);
Object obj = c.newInstance();
return obj;
}catch(Exception e) {
e.printStackTrace();
return null;
}
}
}
Client类
package abstractfactory;
public class Client {
public static void main(String[] args) throws Exception{
SkinFactory skinfactory = (SkinFactory)XMLUtil.getBean();
AbstractButton button = skinfactory.createButton();
AbstractTextBox textBox = skinfactory.createTextBox();
AbstractComboBox comboBox = skinfactory.createComboBox();
button.action();
textBox.action();
comboBox.action();
}
}
.xml配置文件
<?xml version="1.0"?>
<config>
<className>abstractfactory.SpringSkinFactory</className>
<className>abstractfactory.SummerSkinFactory</className>
</config>
三、出现的问题及解决方案
(1)第一个问题比较简单,工厂类与产品类之间的关系很清楚,只包含两种图片产生器以及两种格式的图片,我们需要注意的是在编程时分清接口与实现关系以及在画类图时,搞清楚箭头的指向。
(2)第二个问题实现稍微复杂一点,需要注意在抽象产品中包含蓝色和绿色的不同按钮、文本框以及组合框,这就需要从中抽象出按钮类、文本框类以及组合框类,这里的关系稍微有点复杂,注意在编写代码的时候避免出错。
(3)还有就是XMLUtil类中需要注意的是.xml文件的路径修改。最后在主函数的编写中创建对象时不再使用new创建对象,而是通过从xml配置文件中提取类名并返回实例对象。