模板设计模式和代理模式

一、基于抽象类的模板设计模式:

在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。 换句话说,在软件开发中实现一个算法时,整体步骤很固定、通用,这些步骤已经在父类中写好了。但是某些部分易变,易变部分可以抽象出来,供不同子类实现。这就是一种模板模式。
下面是一个完整的模板模式超类的定义 :
/**
 * 基类声明为抽象类的原因是
 * 其子类必须实现其操作
 */
abstract class AbstractClass {
    /**
     * 模板方法,被声明为final以免子类改变这个算法的顺序
     */
    final void templateMethod() {
    }
    /**
     * 具体操作延迟到子类中实现
     */
    abstract void primitiveOperation1();
    abstract void primitiveOperation2();
    /**
     * 具体操作且共用的方法定义在超类中,可以被模板方法或子类直接使用
     */
    final void concreteOperation() {
        // 实现
    }
    /**
     * 钩子方法是一类"默认不做事的方法"
     * 子类可以视情况决定要不要覆盖它们。
     */
    void hook() {
        // 钩子方法
    }
}

扩展上述类,引入"钩子"方法;超类实现:

abstract class CaffeineBeverage {
    final void prepareRecipe() {
        boilWater();
        brew();
        pourInCup();
        // 如果顾客想要饮料我们才调用加料方法
        if (customerWantsCondiments()){
            addCondiments();
        }
    }
    abstract void brew();
    abstract void addCondiments();
    void boilWater() {
        System.out.println("Boiling water");
    }
    void pourInCup() {
        System.out.println("Pouring into cup");
    }
    /**
     * 钩子方法
     * 超类中通常是默认实现
     * 子类可以选择性的覆写此方法
     * @return
     */
    boolean customerWantsCondiments() {
        return true;
    }
}
子类实现 :
class Tea extends CaffeineBeverage {
    void brew() {
        System.out.println("Steeping the tea");
    }
    void addCondiments() {
        System.out.println("Adding Lemon");
    }
}
class Coffee extends CaffeineBeverage {
    void brew() {
        System.out.println("Dripping Coffee through filter");}
    void addCondiments() {
        System.out.println("Adding Sugar and Milk");
    }
    /**
     * 子类覆写了钩子函数,实现自定义功能
     * @return
     */
    public boolean customerWantsCondiments() {
        String answer = getUserInput();
        if (answer.equals("y")) {
            return true;
        }else {
            return false;
        }
    }
    private String getUserInput() {
        String answer = null;
        System.out.println("您想要在咖啡中加入牛奶或糖吗 (y/n)?");
        Scanner scanner = new Scanner(System.in);
        answer = scanner.nextLine();
        return answer;
    }
}

现实生活中的例子:用代码描述喝咖啡

a.把水烧开 b.将咖啡导入顾客杯子中 c.将咖啡倒入顾客杯子中 d.加糖和牛奶

public class Coffee{
    //一键启动按钮,点这个按钮就能出一杯咖啡
    public void prepareRecipe(){
        boilWater();
        brewCoffeeBag();
        pourInCup();
        addSugarAndMilk();
    }
}

现在不想喝咖啡,想点一杯茶

class Tea{
    public void prepareRecipe(){
        boilWater();
        steepTeaBag();
        pourInCup();
        addLemon();
    }
}

出现的问题:1. 代码出现大量重复(烧水,倒入杯子这两个方法对于所有热饮,大家都是通用的)

2.假设每当扩展一种新的热饮,上述代码全得重写一遍。不方便扩展。

解决问题:将热饮设计为一个父类CaffineBeverage

Coffee extends CaffeineBeverage

Tea extends CaffeineBeverage

烧水和倒入杯子操作子类就可直接使用。对于制作饮品的具体流程,对于顾客来说是不可见的

abstract class CaffeineBeverage{
    //制作流程是标准化的,封装到父类中
    //子类只有使用权不能修改
    public final void prepareRecipe(){
        boilWater();
        brew();
        pourInCup();
        addCondiments();
    }
    //对于浸泡和加调味品来说,不同子类实现细节不同,延迟到子类中去具体实现
    public abstract void brew();
    public abstract  void addCondiments();
    public void pourInCup(){
    }
}
class Coffee extends CaffeineBeverage{
    @Override
    public void brew() {
        System.out.println("brew coffee bag");
    }
    @Override
    public void addCondiments() {
        System.out.println("add sugar and milk");
    }
}
class Tea extends CaffeineBeverage{
    @Override
    public void brew() {
        System.out.println("steep tea bag");
    }
    @Override
    public void addCondiments() {
        System.out.println("add lemon");
    }
}

代码中的细节解释:要保证所有加盟店的饮品在不同门店的味道都是相同的,就需要把制作流程prepareRecipe()封装到父类中,子类只能使用不能修改!

final修饰的方法子类只能使用,不能修改。

对于咖啡和茶来说,泡茶泡咖啡,加奶加柠檬就得具体子类去实现。--父类中无法实现,延迟到具体子类中实现--抽象方法

子类只需要关心子类独有的方法实现即可。共同的方法拿来即用

父类封装了核心方法(算法),子类只能使用不能修改,对于核心方法来说就是一种保护

要扩展一个新的子类,非常容易。

public boolean isCustomerWantsCondiments(){
    return true;
}

钩子方法(hook)--加糖和牛奶,有的顾客就不要。--子类来决定

对于父类来说,制作饮品的最后一步默认都是加调味品

如果有的子类可以选择不加,覆写此方法即可。

二、代理设计模式:(代购)

代理设计模式是基于接口的

代理设计就是为其他对象提供一种代理以控制对这个对象的访问。

一个接口两个实现类,一个是真实业务类,另一个是辅助真实业务的代理类

最终将真实业务传递给代理类来完成整个业务的实现

举例:

顾客:真正付钱的人(提出问题)

代购:帮助买东西(辅助解决真实问题)

class ProxySubject implements ISubject{
    private ISubject realSubject;
    public ProxySubject(ISubject subject){
        this.realSubject = subject;
    }
    public void preHandle(){
        System.out.println("买飞机票去看漂亮妹妹~");
    }
    @Override
    public void buyComputer() {
        preHandle();
        //付钱这个操作是由真实业务来处理的
        this.realSubject.buyComputer();
        postHandle();
    }
    public void postHandle() {
        System.out.println("再回国");
    }
}

代理模式的本质:所有的真实业务操作都会有一个与之辅助的工具类(功能类)共同完成。

代理模式在JavaEE中有着广泛的应用。EJB、WebService、Spring等技术都是代理模式的应用。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值