一.内容说明
某系统日志记录器要求支持多种日志记录方式,如文件记录,数据库记录等,且用户可以根据要求动态选择日志记录方式,现使用工厂方法模型设计该系统.
二.设计类图
三.全部类代码
1.抽象产品类Log(日志记录类)
public interface Log {
public void writeLog();
}
Log作为一个抽象产品类,它可以是一个接口,也可以是一个抽象类,包含了所有产品都具有的业务方法writeLog()。
2.具体产品类FileLog(文件记录类)
public class FileLog implements Log{
@Override
public void writeLog() {
System.out.println("文件记录日志...");
}
}
FileLog是抽象产品Log接口的子类,它是一种具体产品,实现了在Log接口中定义的业务方法writeLog()。
3.具体产品类DatabaseLog(数据库记录类)
public class DatabaseLog implements Log {
@Override
public void writeLog() {
System.out.println("数据库记录日志...");
}
}
DatabaseLog是抽象产品Log接口的另一个子类。
4.抽象工厂类LogFactory(日志记录工厂类)
public interface LogFactory {
public Log createLog();
}
LogFactory是抽象工厂类,它可以是一个接口,也可以是一个抽象类,包含了抽象的工厂方法createLog(),返回一个抽象产品Log类型的对象。
5.具体工厂类FileLogFactory(文件日志记录工厂类)
public class FileLogFactory implements LogFactory {
@Override
public Log createLog() {
System.out.println("文件记录方式...");
return new FileLog();
}
}
FileLogFactory是具体工厂类,是抽象工厂类LogFactory的子类,实现了抽象工厂方法createLog(),在工厂方法中创建并返回一个对象的具体产品。
6.具体工厂类DatabaseLogFactory(数据库日志记录工厂类)
public class DatabaseLogFactory implements LogFactory {
@Override
public Log createLog() {
System.out.println("数据库记录方式...");
return new DatabaseLog();
}
}
DatabaseLogFactory是抽象工厂LogFactory的另一个子类。
7.客户端测试类Client
public class Client {
public static void main(String[] args) {
try {
LogFactory logFactory1 = new FileLogFactory();
Log log1 = logFactory1.createLog();
log1.writeLog();
LogFactory logFactory2 = new DatabaseLogFactory();
Log log2 = logFactory2.createLog();
log2.writeLog();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
四.运行结果
五.分析和总结
1.整体构造:
工厂方法模式是简单工厂模式的进一步抽象和推广。在工厂方法模式中,核心的工厂类不再负责所有产品的创建,而是将具体创建工作交给子类去做。这个核心类仅仅负责给出具体工厂必须实现的接口,而不负责哪一个产品类被实例化这种细节,这使得工厂方法模式可以允许系统在不修改工厂角色的情况下引进新产品。
2.优点:
①在工厂方法模式中,工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节,用户只需要关心所需产品对应的工厂,无须关心创建细节,甚至无须知道具体产品类的类名。
②基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。它能够让工厂可以自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部。工厂方法模式之所以又被称为多态工厂模式,就正是因为所有的具体工厂类都具有同一抽象父类。
③使用工厂方法模式的另一个优点是在系统中加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他的具体工厂和具体产品,而只要添加一个具体工厂和具体产品就可以了,这样,系统的可扩展性也就变得非常好,完全符合“开闭原则”。
3.缺点:
①在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。
②由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。