工厂模式
工厂模式是一种非常常用的创建型设计模式,其提供了创建对象的最佳方式。在创建对象时,不会对客户端暴露对象的创建逻辑,而是通过使用共同的接口来创建对象。
角色
1.抽象产品
2.具体产品
3.抽象工厂
4.具体工厂
使用场景:
1、日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。
2、数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。
3、设计一个连接服务器的框架,需要三个协议,“POP3”、“IMAP”、“HTTP”,可以把这三个作为产品类,共同实现一个接口。
注意事项:
作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过 new 就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。
优点:
1、一个调用者想创建一个对象,只要知道其名称就可以了。 2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。
3、屏蔽产品的具体实现,调用者只关心产品的接口。
缺点:
每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。
案例分析-汽车工厂
需求说明:
- 如前所述,按照汽车生产类图,完成相应的代码设计。
- 创建一个xml配置文件,仿照前面的示例定义一个读取配置文件的工具类,能够从配置文件中读取需要创建的工厂类名。
- 自定义一个应用程序类,完成对上述类的测试。
代码实现
(1)Benz接口
package FactoryMethod;
public interface Benz {
//抽象的产品:提供了产品的接口
public abstract void carColor();
public abstract void carSpeed();
public abstract void carPrice();
}
(2)BenzC180类
package FactoryMethod;
public class BenzC180 implements Benz{
@Override
public void carColor() {
// TODO Auto-generated method stub
System.out.println("BenzC180车颜色是白色的");
}
@Override
public void carSpeed() {
// TODO Auto-generated method stub
System.out.println("BenzC180车速很快");
}
@Override
public void carPrice() {
// TODO Auto-generated method stub
System.out.println("BenzC180车价格为:40万人民币");
}
}
(3)BenzE260类
package FactoryMethod;
public class BenzE260 implements Benz{
@Override
public void carColor() {
// TODO Auto-generated method stub
System.out.println("BenzE260车颜色是黑色的");
}
@Override
public void carSpeed() {
// TODO Auto-generated method stub
System.out.println("BenzE260车,车速很快");
}
@Override
public void carPrice() {
// TODO Auto-generated method stub
System.out.println("BenzE260车,价格是30万人民币");
}
}
(4)BenzFactory接口
package FactoryMethod;
public interface BenzFactory {
//抽象工厂
public abstract Benz createCar();
}
(5)C180Factory类
package FactoryMethod;
public class C180Factory implements BenzFactory{
@Override
public Benz createCar() {
// TODO Auto-generated method stub
System.out.println("C180工厂创造了许多C180车型");
return new BenzC180();
}
}
(6)E260Factory类
package FactoryMethod;
public class E260Factory implements BenzFactory{
@Override
public Benz createCar() {
// TODO Auto-generated method stub
System.out.println("E260工厂创造了许多E260车型");
return new BenzE260();
}
}
(7)ReadXMl类
package FactoryMethod;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import java.io.*;
public class ReadXML {
//该方法用于从XML配置文件中提取具体类类名,并返回一个实例对象
public static Object getObject() {
try {
//创建文档对象
DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dFactory.newDocumentBuilder();
Document doc;
doc = builder.parse(new File("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;
}
}
}
(8)config.xml
<?xml version='1.0'?>
<config>
<className>C180Factory</className>
</config>
(9)测试类
package FactoryMethod;
public class AbstractFactoryTest {
public static void main(String[] args) {
try {
Benz benz;
BenzFactory benzFactory;
benzFactory = (BenzFactory) ReadXML.getObject();
benz = benzFactory.createCar();
benz.carColor();
benz.carSpeed();
benz.carPrice();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
运行结果