代码Github连接 :https://github.com/tangbi123/Tab-Design-Pattern
一、Template Method模式
Template Method:在父类中定义处理流程的框架,在子类中实现具体处理的模式。
1、示例
名字 | 说明 |
---|---|
AbstractDisplay | 只实现了display方法的抽象类 |
CharDisplay | 实现了open、print、close方法的类 |
StringDisplay | 实现了open、print、close方法的类 |
Main | 测试程序行为的类 |
代码清单
1)AbstractDisplay
public abstract class AbstractDisplay {
public abstract void open();
public abstract void print();
public abstract void close();
public final void display(){
open();
for(int i = 0; i < 5; i++)
print();
close();
}
}
2)CharDisplay
public class CharDisplay extends AbstractDisplay{
private char ch;
public 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(">>");
}
}
- StringDisplay
public class StringDisplay extends AbstractDisplay{
private String string;
private int width;
public StringDisplay(String string) {
this.string = string;
this.width = string.getBytes().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("+");
}
}
4)main
public class main {
public static void main(String[] args) {
AbstractDisplay d1 = new CharDisplay('H');
AbstractDisplay d2 = new StringDisplay("Hello world.");
AbstractDisplay d3 = new StringDisplay("你好世界");
d1.display();
d2.display();
d3.display();
}
}
2、角色
1)AstractClass(抽象类) =》 AbstractDisplay
不仅负责实现模板方法,还负责声明在模板方法中所使用到的抽象方法。
抽象方法由子类ConcreteClass角色实现。
2)ConcreteClass(具体类) =》 CharDisplay、StringDisplay
负责具体实现AbstractClass角色中定义的抽象方法。
3、思路要点
1)使逻辑处理通用化
发现Bug,修改模板方法即可。
2)父类和子类协作
父类子类紧密联系,共同工作。
在子类实现父类生命的抽象方法时,必须要理解这些抽象方法被调用的时机。
在看不到父类的源代码情况,想要编写出子类是非常困难的。
3)父类与子类的一致性
子类实例,都是先保存在父类类型的变量中,然后再来调用方法。
里氏替换:无论在父类类型的变量中保存哪个子类实例,程序都可以正常工作。
4、延申:类的层次与抽象类
1)父类对子类的要求(“子类责任”)
理解类的层次,通常站在 子类 角度思考:
1、子类可以使用父类定义的方法
2、可以通过子类中增加方法以实现新的功能
3、在子类中重写父类方法可以改变程序的行为。
站在父类的角度思考:
1、期待子类去实现抽象方法
2、要求子类去实现抽象方法
2)抽象类的意义
在抽象阶段确定: 处理的流程
3)父类与子类之间的协作
父类实现方法过多: 子类轻松,但降低子类的灵活性
父类实现方法过少:子类臃肿不堪,各子类间代码重复
Template Method模式中,
父类:处理流程的定义;子类:具体的处理。
但是对于如何划分处理级别、那些处理需要由父类完成、那些处理需要交给子类负责,没有定式,都需要由负责程序设计的开发人员来决定。
Factory Method模式
父类决定实例的生成方式,但并不决定索要生成的具体的类,具体的处理全部交给子类负责。
将生成实例的框架 和 实际负责生成实例的类 解耦
1、示例
包 | 名字 | 说明 |
---|---|---|
framework | Product | 之定义抽象方法user的抽象类 |
framework | Factory | 实现了create方法的抽象类 |
idcard | IDCard | 实现了user方法的类 |
idcard | IDCardFactory | 实现了createProduct、registerProduct方法的类 |
无名 | Main | 测试程序行为的类 |
代码清单
1)Product 接口
package Factory_Method.framework;
public abstract class Product {
public abstract void use();
}
2)Factory 接口
package Factory_Method.framework;
public abstract class Factory {
public final Product create(String owner){
Product product = createProduct(owner);
registerProduct(product);
return product;
}
protected abstract Product createProduct(String owner);
protected abstract void registerProduct(Product product);
}
3)IDCard 类
package Factory_Method.idcard;
import Factory_Method.framework.Product;
public class IDCard extends Product {
private String owner;
public IDCard(String owner){
System.out.println("制作" + owner + "的ID卡");
this.owner = owner;
}
public String getOwner() {
return owner;
}
@Override
public void use() {
System.out.println("使用" + owner + "的ID卡");
}
}
4)IDCardFactory 类
import Factory_Method.framework.Product;
import java.util.ArrayList;
import java.util.List;
public class IDCardFactory extends Factory {
private List owner = new ArrayList();
@Override
protected Product createProduct(String owner) {
return new IDCard(owner);
}
@Override
protected void registerProduct(Product product) {
owner.add(((IDCard)product).getOwner());
}
public List getOwner(){
return owner;
}
}
- main
package Factory_Method;
import Factory_Method.framework.Factory;
import Factory_Method.framework.Product;
import Factory_Method.idcard.IDCardFactory;
public class main {
public static void main(String[] args) {
Factory factory = new IDCardFactory();
Product card1 = factory.create("小明");
Product card2 = factory.create("小红");
Product card3 = factory.create("小军");
card1.use();
card2.use();
card3.use();
}
}
2、角色
1)Product =》 Product
定义了生成实例所持有的接口(API),但具体的处理则由子类ConcreteProduct角色决定。
2)Create => Factory
负责生成Product角色的抽象类,但具体的处理由子类 ConcreteCreator角色决定。
Create角色 只知道, 只要调用Product角色和 生成实例的方法, 就可以生成Product的实例。=》(createProduct)
3)ConcreteProduct => IDCard
决定了具体的产品。
4)ConcreteCreator => IDCardFactory
负责生成具体的产品。
‘
3、思路要点
1)框架与具体加工
2)生成实例 三种方法
createProduct 方法
1、指定其为抽象类, 子类继承,就需要实现该方法。
2、实现默认处理
3、在其中抛出异常
3)使用模式与开发人员之间的沟通
必须要理解父类中所定义的处理的框架 和 它里面所使用的抽象方法,然后阅读代码,了解这些抽象方法在子类中的实现才行。