分解共性(Factoring Commonality)
应用“一次并且仅有一次”原则,放置变化的编码到一个方法中最基本的模式。
这个能够以两种方式来表现:
策略模式(strategy):运行时选择算法。
策略模式也能够添加一个“上下文”的代理类,来控制特别策略对象的选择和使用—很像状态模式!看看下面的代码:
//: strategy:StrategyPattern.java
package strategy;
import com.bruceeckel.util.*; // Arrays2.toString()
import junit.framework.*;
// The strategy interface:
interface FindMinima {
// Line is a sequence of points:
double[] algorithm(double[] line);
}
// The various strategies:
class LeastSquares implements FindMinima {
public double[] algorithm(double[] line) {
return new double[] { 1.1, 2.2 }; // Dummy
}
}
class NewtonsMethod implements FindMinima {
public double[] algorithm(double[] line) {
return new double[] { 3.3, 4.4 }; // Dummy
}
}
class Bisection implements FindMinima {
public double[] algorithm(double[] line) {
return new double[] { 5.5, 6.6 }; // Dummy
}
}
class ConjugateGradient implements FindMinima {
public double[] algorithm(double[] line) {
return new double[] { 3.3, 4.4 }; // Dummy
}
}
// The "Context" controls the strategy:
class MinimaSolver {
private FindMinima strategy;
public MinimaSolver(FindMinima strat) {
strategy = strat;
}
double[] minima(double[] line) {
return strategy.algorithm(line);
}
void changeAlgorithm(FindMinima newAlgorithm) {
strategy = newAlgorithm;
}
}
public class StrategyPattern extends TestCase {
MinimaSolver solver =
new MinimaSolver(new LeastSquares());
double[] line = {
1.0, 2.0, 1.0, 2.0, -1.0,
3.0, 4.0, 5.0, 4.0 };
public void test() {
System.out.println(
Arrays2.toString(solver.minima(line)));
solver.changeAlgorithm(new Bisection());
System.out.println(
Arrays2.toString(solver.minima(line)));
}
public static void main(String args[]) {
junit.textui.TestRunner.run(StrategyPattern.class);
}
} ///:~
注意,与模板模式的相似性,模板模式声明了区别,它有多于一种方法去调用,分段的处理事情。然而,它并非不可能策略对象有多于一个方法调用,参考Shalloway的订单满足系统在每个策略的国家信息。
JDK中策略的例子:comparator objects 。
政策(Policy):一般的策略
尽管GOF认为Policy仅仅是strategy的另外一个名字,他们策略模式的应用隐含的假定策略对象中一个单一的方法。你打碎变化的算法作为单个的代码片断。
其他人应用Policy代表一个对象,有从类到类独立变化的多个方法。这比限制单一方法提供了更大的灵活性。
例如,无论什么时候你创建一个applet,你会使用一个应用程序框架:从JApplet继承并且覆盖init()方法。Applet机制(一个模板方法)通过绘制屏幕不眠不休,调度事件循环,重新定义大小等等。
模板方法的一个重要特点,它定义在基类中的不能被改变,它有时是一个private方法,但几乎常常是被定义成final。它调用另外的基类方法(你覆盖的方法)去执行操作,但是它经常被作为初始化过程的部分被调用(这样客户端程序不必能直接调用它)
//: templatemethod:TemplateMethod.java
// Simple demonstration of Template Method.
package templatemethod;
import junit.framework.*;
abstract class ApplicationFramework {
public ApplicationFramework() {
templateMethod(); // Dangerous!
}
abstract void customize1();
abstract void customize2();
final void templateMethod() {
for (int i = 0; i < 5; i++) {
customize1();
customize2();
}
}
}
// Create a new "application":
class MyApp extends ApplicationFramework {
void customize1() {
System.out.print("Hello ");
}
void customize2() {
System.out.println("World!");
}
}
public class TemplateMethod extends TestCase {
MyApp app = new MyApp();
public void test() {
// The MyApp constructor does all the work.
// This just makes sure it will complete
// without throwing an exception.
}
public static void main(String args[]) {
junit.textui.TestRunner.run(TemplateMethod.class);
}
} // /:~
基类的构造函数负责执行必要的初始化,然后启动这个运行应用程序(在一个GUI应用中,“发动机”主要是事件循环)的“发动机”(模板方法)。客户端程序简单的定义了custom1()和custom2()并且这个应用做好了运行准备。
练习:
1.创建一个框架,在名行中得到一个文件名称的列表。打开每个文件除了最后一个用于读写的文件。这个框架处理每一个输入文件,用一个未定的策略并且记录输出到最后一个文件。继承这个自定义的框架创建两个独立的应用程序。
1)转换这个文件的所有字母为大写字母
2)在这个文件中搜索第一个文件中给定的单词
omencathay译
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/25966/viewspace-53316/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/25966/viewspace-53316/