模板方法模式
父类写一些抽象方法,子类来实现他们
示例
这里我们希望实现一个打印的功能。预计是设计两个类,一个用来打印字符,另一个用来打印字符串。
抽象了一个基类设计打印的一些细节,把整个打印流程总结成了3个部分,open, print和close
- open() 负责打印一些初始东西
- print() 负责打印实际内容
- close() 负责打印一些结尾的东西
具体来说
- 打印字符我们希望打印成
<<xxx>>
这个样子 - 打印字符串我们希望打印5次,并且用一个框框包起来,具体看例子。
// 这里用抽象类而不是接口,是因为父类也要实现一些方法
public abstract class AbstractDisplay {
public abstract void open();
public abstract void print();
public abstract void close();
// final表示不可被重写
public final void display() {
open();
for (int i = 0; i < 5; i++) {
print();
}
close();
}
}
class CharDisplay extends AbstractDisplay {
public char ch;
CharDisplay(char ch) {
this.ch = ch;
}
@Override
public void open() {
System.out.print("<<");
}
@Override
public void print() {
System.out.print(ch);
}
@Override
public void close() {
System.out.println(">>");
}
}
class StringDisplay extends AbstractDisplay {
private String string;
private int width;
public StringDisplay(String str) {
string = str;
width = str.length();
}
@Override
public void open() {
printLine();
}
@Override
public void print() {
System.out.println("|" + string + "|");
}
@Override
public void close() {
printLine();
}
private void printLine() {
System.out.print("+");
for (int i = 0; i < width; i++) {
System.out.print('-');
}
System.out.println("+");
}
}
public class TemplateMethodTest {
public static void main(String[] args) {
AbstractDisplay stringDisplay = new StringDisplay("Hello Destiny");
AbstractDisplay charDisplay = new CharDisplay('a');
stringDisplay.display();
charDisplay.display();
}
}
/*
打印字符串
+-------------+
|Hello Destiny|
|Hello Destiny|
|Hello Destiny|
|Hello Destiny|
|Hello Destiny|
+-------------+
打印字符
<<aaaaa>>
*/
注意
- 使用模板方法的好处是将处理一件事的流程和逻辑更清晰化了。以后在修改细节的时候,只需要新继承一个类,然后重写那些模板方法就行了。
- 编写子类的时候必须要了解父类的运行逻辑
- 模板方法遵循了里氏替换原则,所有的子类在任何一个需要父类参数的函数中都能正常运行。
相关设计模式
- 策略(strategy)模式
- 工厂方法(factory method)模式
工厂方法模式
工厂方法将创建一个类需要做的一堆乱七八糟的事情放到了一个工厂类里面。用户只需要调用这个工厂类的方法就可以创建对象了。
示例
看个例子。这里我们需要构造IDCard对象。但是,每次构造一个IDCard都需要把这个IDCard注册到一个地方保存。
那么对于用户而言,每次new一个IDCard是不是就需要register一次。
我们完全可以把这个操作交给别的类来做。
具体来说就是,将new和register这两个行为交给工厂方法去做,然后用户直接调用factory的create接口就行了。
public abstract class Factory {
// 这是工厂必须有的方法,用来创建Product
// 最简单就是直接在这个函数里面new一个Product
// 但是我们将这个操作放到了createProduct后面去了
public final Product create(String owner) {
Product p = createProduct(owner);
registerProduct(p);
return p;
}
// 这些都是工厂函数,为了创建Product所需要做的事情
protected abstract Product createProduct(String owner);
protected abstract void registerProduct(Product product);
}
public abstract class Product {
// 这个是产品的方法
public abstract void use();
}
public class IDCard extends Product {
private String owner;
public IDCard(String owner) {
System.out.println("制作" + owner + "的ID卡。");
this.owner = owner;
}
@Override
public void use() {
System.out.println("使用" + owner + "的ID卡");
}
public String getOwner() {
return owner;
}
}
public class IDCardFactory extends Factory {
private List owners = new ArrayList();
@Override
protected Product createProduct(String owner) {
return new IDCard(owner);
}
@Override
protected void registerProduct(Product product) {
owners.add(((IDCard)product).getOwner());
}
public List getOwners() {
return owners;
}
}
public class FactoryMethodTest {
public static void main(String[] args) {
Factory factory = new IDCardFactory();
// 这里用factory构造,我们就不需要手动注册了,直接交给factory完成就行了
Product card1 = factory.create("Destiny");
Product card2 = factory.create("Bob");
card1.use();
card2.use();
}
}
角色
这里可以看一下具体的关系,Creator就是工厂,Product就是用户想要的类。Creator里面一堆工厂方法是为了创建Product所需要做的事情。
如果没有Creator,那这些事情就直接上到用户了。
相关设计模式
- 模板方法(template method)模式
- 单例(singleton)模式
- 组合模式(composite)模式
- 迭代器(iterator)模式