图解设计模式 --交给子类

代码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(">>");
    }
}
  1. 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;
    }
}
  1. 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)使用模式与开发人员之间的沟通
必须要理解父类中所定义的处理的框架 和 它里面所使用的抽象方法,然后阅读代码,了解这些抽象方法在子类中的实现才行。

上一篇:Spring Boot注入RestTemplate ,出现空指针解决办法


下一篇:memcached实战系列(五)Memcached: List all keys 查询所有的key