设计模式-模板方法

在代码结构上:

1 一个抽象类:不是接口 因为里面有个实现方法,多个抽象方法
2 这个抽象类里有一个主方法:cook(),
3 主方法里面包含几个共性的固定的抽象方法(getRice(),fry(),getOut()),并且顺序一定的。
4 用户访问类DanChaoFanCooker里面依赖关联这个抽象类。

这边引用:https://www.cnblogs.com/08shiyan/p/4989203.html 和策略模式的比较

模板方法的意图:定义一个算法流程,将一些特定步骤的具体实现、延迟到子类。使得可以在不改变算法流程的情况下,通过不同的子类、来实现“定制”流程中的特定的步骤。

  策略模式的意图:使不同的算法可以被相互替换,而不影响客户端的使用。

  在意图上看,模板方法更加强调:

  1)定义一条线(算法流程),线上的多个点是可以变化的(具体实现在子类中完成),线上的多个点一定是会被执行的,并且一定是按照特定流程被执行的。

  2)算法流程只有唯一的入口,对于点的访问是受限的【通常用受保护的虚函数来定义可变点】。

  策略模式更注重于: 一个“策略”是一个整体的(完整的)算法,算法是可以被整体替换的。而模板方法只能被替换其中的特定点,算法流程是固定不可变的。

  

  在这样的细节上看来,模板方法 和 一组策略模式 是不可以划等号的。

谢霆锋的风味,有一期是去扬州比赛蛋炒饭。米-不同的组米可以不同,炒,怎么炒用什么锅不关心,

炒好了用什么盛饭不关心,用户是只要选择那组然后就等着吃蛋炒饭。

下面代码代码实现:

/**
 * 里面方法的定义 有参 无参无限制, 看实际业务需求。
 *
 * @author flynn
 * @datetime 2018-08-20 11:15
 */
public abstract class DanChaoFan {
    String rice;
    String fire;

    //获取大米。。。其他辅材
    abstract String getRice();

    //炒
    abstract void fry();

    //盛出来
    abstract FriedRice getOut();

    // 蛋炒饭的工序 一般固定下来就不变了,否则各个子类都要修改
    public FriedRice cook() {
        getRice();
        fry();
        return getOut();
    }
}

用户用户访问类即用户选择的对象。 

/**
 * 炒饭师傅
 */
public class DanChaoFanCooker {
    //依赖注入蛋炒饭对象
    private DanChaoFan danChaoFan;

    public DanChaoFanCooker(DanChaoFan danChaoFan) {
        this.danChaoFan = danChaoFan;
    }

    public FriedRice getDanChaoFan() {
        return danChaoFan.cook();
    }

    //客户换个口味的蛋炒饭
    void changeDanChaoFan(DanChaoFan danChaoFan) {
        this.danChaoFan = danChaoFan;
    }
}

zile谢大厨的蛋炒饭-子类是实现具体的业务

public class XieCookerDanChaoFan extends DanChaoFan {
    @Override
    String getRice() {
        rice = "谢大厨用的五常大米";
        return rice;
    }

    @Override
    void fry() {
        fire = "谢大厨用的山木的火,大铁锹还有加入了香肠、美女帮忙...";
    }

    @Override
    FriedRice getOut() {
        FriedRice friedRice = new FriedRice();
        friedRice.setResult(fire + rice);
        return friedRice;
    }

}

子类-扬州大厨的蛋炒饭

public class YangCookerDanChaoFan extends DanChaoFan {

    @Override
    String getRice() {
        rice = "扬州大厨用的自己种的大米";
        return rice;
    }

    @Override
    void fry() {
        fire = "扬州大厨用的天然气,大铁锹还有加入了梅干菜...";
    }

    @Override
    FriedRice getOut() {
        return new FriedRice(fire + rice);
    }

}

测试:顾客选择不同组的厨师选择不同的蛋炒饭来吃

public class MainTest {
    public static void main(String[] args) {
        DanChaoFanCooker cooker = new DanChaoFanCooker(new YangCookerDanChaoFan());
//        DanChaoFanCooker xieCooker = new DanChaoFanCooker(new XieCookerDanChaoFan());
        FriedRice friedRice = cooker.getDanChaoFan();
        System.out.println("先尝尝扬州炒饭之神的蛋炒饭:" + friedRice);
        cooker.changeDanChaoFan(new XieCookerDanChaoFan());
        friedRice = cooker.getDanChaoFan();
        System.out.println("换个口味,尝尝谢大厨的蛋炒饭:" + friedRice);
    }
}

结果:

案例。当时做app的首页,各个楼层的实现就是模板方法。(每个楼层里面的布局几乎都不一样,主要是嵌套太深,简单地使用listview或者recycleview性能很不好。当然后面才优化)

模式缺点

       需要为每一个基本方法的不同实现提供一个子类,如果父类中可变的基本方法太多,将会导致类的个数增加,系统更加庞大,设计也更加抽象,此时,可结合桥接模式来进行设计

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值