设计模式 - 工厂方法模式(Factory Method)

工厂方法模式 (Factory Method)

定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使一个类的实例化延迟到其子类。引入多态创建对象。

一个层次中的类都有相似实现一个方法(AnOperation), 只是这个方法中对象创建的步骤不同。工厂方法通常在模板方法中被调用。

下面的例子通过学习Log4j APIs,运用重构技术实现模板方法和工厂方法模式:

Log4j 有ConsoleAppender and FileAppender 两个类,用于将log 输出到控制台和制定文件中,基于JUnit4写两个测试类学习这两种Appender如何工作.

Step 1: 写两个测试类,分别测试将debug logs输出到控制台和指定的文件中。

 

public class ConsoleAppenderTest{
	private Logger logger = Logger.getLogger(ConsoleAppenderTest.class);
	@Test
	public void testConsoleAppender() {
		<font color="red">ConsoleAppender appender = new ConsoleAppender(new SimpleLayout());</font>
		logger.addAppender(appender);
		logger.setLevel((Level) Level.DEBUG);
		logger.debug("Debug logs");
	}
}

 

public class FileAppenderTest{
	private Logger logger = Logger.getLogger(FileAppenderTest.class);
	@Test
	public void testFileAppender(){
		FileAppender appender = null;
		try {
			appender = new FileAppender(new SimpleLayout(), "d:/log.txt", false);
		} catch (Exception e) {
			fail();
			//do something
		}
		logger.addAppender(appender);
		logger.setLevel((Level) Level.DEBUG);
		logger.debug("Debug logs");
	}
}
		FileAppender appender = null;
		try {
			appender = new FileAppender(new SimpleLayout(), "d:/log.txt", false);
		} catch (Exception e) {
			fail();
			//do something
		}
		logger.addAppender(appender);
		logger.setLevel((Level) Level.DEBUG);
		logger.debug("Debug logs");
	}
}


Step 2: 上面两个测试类测试的方法类似,只是创建的对象不同 (ConsoleAppender, FileAppender), 这两个对象类型属于同一个类层次(继承WriterAppender),符合应用工厂方法(Factory Method)模式。首先要提取方法(Extract Method) 对这两个类进行重构:

 

 

 

public class ConsoleAppenderTest{
	private Logger logger = Logger.getLogger(ConsoleAppenderTest.class);
	@Test
	public void testConsoleAppender() {
		WriterAppender appender = createAppender();
		logger.addAppender(appender);
		logger.setLevel((Level) Level.DEBUG);
		logger.debug("Debug logs");
	}
	//Extract method
	WriterAppender createAppender() { 
		return new ConsoleAppender(new SimpleLayout());
	}
}

 

public class FileAppenderTest{
	private Logger logger = Logger.getLogger(FileAppenderTest.class);
	@Test
	public void testFileAppender() {
		WriterAppender appender = createAppender();
		logger.addAppender(appender);
		logger.setLevel((Level) Level.DEBUG);
		logger.debug("Debug logs");
	}
	//Extract method
	WriterAppender createAppender() {
		FileAppender appender = null;
		try {
			appender = new FileAppender(new SimpleLayout(), "d:/log.txt", false);
		} catch (Exception e) {
			fail();
			//do something
		}
		return appender;
	}
}


Step 3: 两个测试类中方法 testConsoleAppender() 和 testFileAppender()内容相同,可以重命名(Rename Method)使其方法名相同; 两个测试类中都有相同签名的createAppender方法,提炼父类(Extract Superclass), 然后方法上移(Pull up Method), 形成模板方法模式(Template Method).

 

 

public abstract class AppenderTest { //Extract superclass
	private Logger logger = Logger.getLogger(AppenderTest.class);
	@Test
	public void testAppender() {//Rename method and Pull up method  (template method)
		WriterAppender appender = createAppender();
		logger.addAppender(appender);
		logger.setLevel((Level) Level.DEBUG);
		logger.debug("Debug logs");
	}

	abstract WriterAppender createAppender(); 
}

 

public class ConsoleAppenderTest extends AppenderTest {
	WriterAppender createAppender() {
		return new ConsoleAppender(new SimpleLayout());
	}
}

 

public class FileAppenderTest extends AppenderTest {
	WriterAppender createAppender() { 
		FileAppender appender = null;
		try {
			appender = new FileAppender(new SimpleLayout(), "d:/log.txt", false);
		} catch (Exception e) {
			fail();
			//do something
		}
		return appender;
	}
}


不是一开始编程的时候就运用模式设计,而是随着需求的变化,引起代码的改变,通过重构代码改进设计以实现模式,从而减少代码重复和可复用代码。

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值