场景:需使用代码方式实现,考完试后,将各个学生的试卷及答案誊抄一份。
假如有两个学生的试卷誊抄完毕.
// 学生A
public class TestPaperA {
// 试题1
public void testQuestion1() {
System.out.println("问题一:XXXXXXXX[] A.xx B.xx C.xx D.xx ");
System.out.println("答案 A");
}
// 试题2
public void testQuestion2() {
System.out.println("问题二:XXXXXXXX[] A.xx B.xx C.xx D.xx ");
System.out.println("答案 A");
}
// 试题3
public void testQuestion3() {
System.out.println("问题三:XXXXXXXX[] A.xx B.xx C.xx D.xx ");
System.out.println("答案 A");
}
}
// 学生B
public class TestPaperB {
// 试题1
public void testQuestion1() {
System.out.println("问题一:XXXXXXXX[] A.xx B.xx C.xx D.xx ");
System.out.println("答案 B");
}
// 试题2
public void testQuestion2() {
System.out.println("问题二:XXXXXXXX[] A.xx B.xx C.xx D.xx ");
System.out.println("答案 B");
}
// 试题3
public void testQuestion3() {
System.out.println("问题三:XXXXXXXX[] A.xx B.xx C.xx D.xx ");
System.out.println("答案 B");
}
}
System.out.println("学生A的试卷");
TestPaperA a = new TestPaperA();
a.testQuestion1();
a.testQuestion2();
a.testQuestion3();
System.out.println("学生B的试卷");
TestPaperB b = new TestPaperB();
b.testQuestion1();
b.testQuestion2();
b.testQuestion3();
一眼看出,很多重复的代码,直接进行提炼抽离。此例中,试卷都是一样的,而答案是不同的,我们直接将重复的代码提炼,然后学生去继承它即可。
// 试卷类
public abstract class TestPaper {
// 3道题的答案
protected abstract String answer1();
protected abstract String answer2();
protected abstract String answer3();
// 试题1
public void testQuestion1() {
System.out.println("问题一:XXXXXXXX[] A.xx B.xx C.xx D.xx ");
System.out.println("答案 " + answer1());
}
// 试题2
public void testQuestion2() {
System.out.println("问题二:XXXXXXXX[] A.xx B.xx C.xx D.xx ");
System.out.println("答案 " + answer2());
}
// 试题3
public void testQuestion3() {
System.out.println("问题三:XXXXXXXX[] A.xx B.xx C.xx D.xx ");
System.out.println("答案 " + answer3());
}
}
学生类只需要继承它,然后填写自己的答案即可。因为父类已经建立好了所有重复的模板
// 学生A
public class TestPaperA extends TestPaper{
@Override
protected String answer1() {
return "A";
}
@Override
protected String answer2() {
return "A";
}
@Override
protected String answer3() {
return "A";
}
}
System.out.println("学生A的试卷");
TestPaper a = new TestPaperA();
a.testQuestion1();
a.testQuestion2();
a.testQuestion3();
那么上述的例子中,用的一种设计模式就是模板方法
模式。定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤。
结构图及代码示例如下:
public abstract class AbstractClass {
// 模板方法(所有重复的代码都放入这里)
public void templateMethod() {
...
}
// 子类的特定实现
public abstract void primitiveOperation1();
public abstract void primitiveOperation2();
}
public class ConcreteClassA extends AbstractClass {
@Override
public void primitiveOperation1() {
System.out.println("A类具体实现一");
}
@Override
public void primitiveOperation2() {
System.out.println("A类具体实现二");
}
}
模板方法是通过把不变行为搬到父类(超类),去除子类中重复代码来体现它的优势。
模板方法是提供了一个代码复用平台。
当不变的和可变行为在方法的实现中混合在一起的时候,不变行为就会在类中重复出现。我们通过模板方法将这些行为搬移到单一的地方,这样帮助子类摆脱重复的不变行为的纠缠。
以一个股票买卖的例子来理解一下,现在有股票、国债、房产,买入卖出代码如下:
// 股票1
public class Stock1 {
public void buy() {
System.out.println("股票1买入");
}
public void sell() {
System.out.println("股票1卖出");
}
}
// 股票2
class Stock2 {
public void buy() {
System.out.println("股票2买入");
}
public void sell() {
System.out.println("股票2卖出");
}
}
// 国债1
public class NationalDebt1 {
public void buy() {
System.out.println("国债买入");
}
public void sell() {
System.out.println("国债卖出");
}
}
// 房产
class Realty1 {
public void buy() {
System.out.println("房产买入");
}
public void sell() {
System.out.println("房产卖出");
}
}
Stock1 stock1 = new Stock1();
Stock2 stock2 = new Stock2();
NationalDebt1 nd1 = new NationalDebt1();
Realty1 rt1 = new Realty1();
// 买入
stock1.buy();
stock2.buy();
nd1.buy();
rt1.buy();
// 卖出
stock1.sell();
stock2.sell();
nd1.sell();
rt1.sell();
外观模式
增加一个基金类,结构图
public class Fund {
Stock1 stock1;
Stock2 stock2;
NationalDebt1 nd1;
Realty1 rt1;
public Fund() {
stock1 = new Stock1();
stock2 = new Stock2();
nd1 = new NationalDebt1();
rt1 = new Realty1();
}
public void buyFund() {
stock1.buy();
stock2.buy();
nd1.buy();
rt1.buy();
}
public void sellFund() {
stock1.sell();
stock2.sell();
nd1.sell();
rt1.sell();
}
}
Fund fund = new Fund();
fund.buyFund();
fund.sellFund();
外观模式:为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
首先在设计阶段,应该有意识将不同的两个层进行分离。其次,在开发阶段,子系统往往因为不断的重构演化而变得越来越复杂,增加外观模式可以提供一个简单的接口减少它们之间的依赖。
还可以在新系统中使用外观模式,创建一个Facade类(外观模式类),来提供设计粗糙或高复杂度的遗留代码的比较清晰简单的接口,让新系统与Facade对象交互,Facade与遗留代码交互完成复杂的工作。