当我们想做一件事的时候,我们可以给我们做的事列一个流程
让我们来举一个例子:
eg:买火车票
流程如下:
- 查看余票
- 买票
- 取票
- 购票成功
买火车票这件事可以分为困难的流程和简单的流程
简单的流程:
- 查看余票
- 购票成功
困难的流程
- 买票
- 取票
因为我们买票可以是:网上买票,车站买票,服务点买票
取票可以是:快递取票,车站取票,服务点取票
背景介绍完毕:
我们用具体的代码来体会一下这个设计模式:
我们先写一个BuyTicket类,里面有一个buyTicket方法,我们先完成简单的第一步查看余票
class BuyTicket{
public void buyTicket() {
//1.查看余票
System.out.println("查看余票"); //我打印只是表示查看余票这个意思
//2.买票
}
}
不好,买票这么多方法(每种买票的方法可以理解为一种算法),我不知道怎么写它。没关系我们把不会的先写成抽象方法,具体的实现以后再说(记得抽象方法所在的类一定是抽象类哦)
abstract class BuyTicket{
public void buyTicket() {
//1.查看余票
System.out.println("查看余票");
//2.买票
buy();
}
public abstract void buy();
}
类似的我们把我们暂时不会的或者难的步骤先写成抽象方法。现在我们来进一步完善
abstract class BuyTicket{
public void buyTicket() {
//1.查看余票
System.out.println("查看余票");
//2.买票
buy();
//3.取票
getTicket();
//4.购票成功
System.out.println("购票成功");
}
public abstract void getTicket();
public abstract void buy();
}
啊,终于完成了,过了两天(相当于我想好用什么算法了),我觉定好了怎么买票(网上订票)和怎么取票了(快递取票)。
那我就新建一个类继承这个抽象类,让他实现的我抽象方法
abstract class BuyTicket{
public void buyTicket() {
//1.查看余票
System.out.println("查看余票");
//2.买票
buy();
//3.取票
getTicket();
//4.购票成功
System.out.println("购票成功");
}
public abstract void getTicket();
public abstract void buy();
}
class TwoDaysLater extends BuyTicket{
@Override
public void getTicket() {
System.out.println("快递取票");
}
@Override
public void buy() {
System.out.println("网上订票");
}
}
ok,终于完成了,让我们加上测试类来运行吧
package com.buy.ticket;
public class Demo_BuyTicket {
public static void main(String[] args) {
TwoDaysLater tdl = new TwoDaysLater();
tdl.buyTicket();
}
}
abstract class BuyTicket{
public void buyTicket() {
//1.查看余票
System.out.println("查看余票");
//2.买票
buy();
//3.取票
getTicket();
//4.购票成功
System.out.println("购票成功");
}
public abstract void getTicket();
public abstract void buy();
}
class TwoDaysLater extends BuyTicket{
@Override
public void getTicket() {
System.out.println("快递取票");
}
@Override
public void buy() {
System.out.println("网上订票");
}
}
我以为一切都在掌握中的时候,12306突然崩了,我只能去火车站买票了。(
package com.buy.ticket;
public class Demo_BuyTicket {
public static void main(String[] args) {
TwoDaysLater tdl = new TwoDaysLater();
tdl.buyTicket();
}
}
abstract class BuyTicket{
public void buyTicket() {
//1.查看余票
System.out.println("查看余票");
//2.买票
buy();
//3.取票
getTicket();
//4.购票成功
System.out.println("购票成功");
}
public abstract void getTicket();
public abstract void buy();
}
class TwoDaysLater extends BuyTicket{
@Override
public void getTicket() {
System.out.println("快递取票");
}
@Override
public void buy() {
System.out.println("车站订票");
}
}
大家已经看出来了。当需求变了,我们不用去修改它的流程(抽象类abstract class BuyTicket),只用修改子类(class TwoDaysLater extends BuyTicket),此时一个优点就体现出来了:我不用再改买票的4个流程,我只用修改我的TwoDaysLater类的重写方法buy()就行了。假如工作中客户的需求多变,我们这样设计的优势就体现出来了)。
细心的同学会发现一个问题,如果有人修改我们的流程怎么办,我们作为设计者肯定不愿意让别人修改我们的流程,那我们就把我们的抽象类abstract class BuyTicket中的buyTicket()方法加一个final(public final void buyTicket()),让子类不能重写我们的这个方法。我们的流程也就不能被别人修改。
package com.buy.ticket;
public class Demo_BuyTicket {
public static void main(String[] args) {
TwoDaysLater tdl = new TwoDaysLater();
tdl.buyTicket();
}
}
abstract class BuyTicket{
public final void buyTicket() {
//1.查看余票
System.out.println("查看余票");
//2.买票
buy();
//3.取票
getTicket();
//4.购票成功
System.out.println("购票成功");
}
public abstract void getTicket();
public abstract void buy();
}
class TwoDaysLater extends BuyTicket{
@Override
public void getTicket() {
System.out.println("快递取票");
}
@Override
public void buy() {
System.out.println("车站订票");
}
}
当然任何事物都有两面性:他的坏处就是,当我们必须要修改流程的时候,会变得很复杂。