Java设计模式——装饰器模式、适配器模式、外观模式

时间:2022-10-09 22:01:20

什么是装饰器模式

装饰器模式,动态的将责任附加到对象上,若要扩展功能,装饰器提供了比继承更有弹性的替代方案。

举例说明

我们定义一种饮料,它有描述信息,还有价格,如下

public abstract class Drink {

    String desc = "nothing";

    public String getDesc() {
        return desc;
    }

    public abstract double cost();
}

然后定义咖啡,是一种饮料,它有自己的描述和价格

public class Coffee extends Drink {

    public Coffee() {
        this.desc = "Coffee";
    }

    public double cost() {
        return 1.2;
    }
}

咖啡可以有不同的口味,而且不同的口味所需要的额外价格不同,这时可以用装饰器方法来实现口味对饮料的装饰,如下:

public class Milk extends Drink {

    private Drink drink;

    public Milk(Drink water) {
        this.drink = water;
    }

    public double cost() {
        return drink.cost() + 1;
    }

    @Override
    public String getDesc() {
        return drink.getDesc() + ", Milk";
    }
}

下面我们创建一个测试类,要演示如何动态的装饰。如下:

class Test {
    public static void main(String[] args){
        Drink drink = new Coffee();
        System.out.println(drink.getDesc() + ", cost " + drink.cost());
        drink = new Milk(drink);
        System.out.println(drink.getDesc() + ", cost " + drink.cost());
        drink = new Milk(drink);
        System.out.println(drink.getDesc() + ", cost " + drink.cost());
    }
}

输出结果为:

Coffee, cost 1.2
Coffee, Milk, cost 2.2
Coffee, Milk, Milk, cost 3.2

适配器模式

将一个类的接口,转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。
比如我们鸭子类,鹅类,他们有自己的叫的方法和飞行的方法如下:

public interface Duck {

    void quack();

    void fly();
}


public class AKindDuck implements Duck {

    public void quack() {
        System.out.println("A kind duck quack");
    }

    public void fly() {
        System.out.println("A kind duck fly");
    }
}

鹅类

public interface Turkey {

    void gobble();

    void fly();
}


public class WildTurkey implements Turkey {

    public void gobble() {
        System.out.println("wild gobble");
    }

    public void fly() {
        System.out.println("wild run");
    }
}

为了让鹅类能适配成鸭子类,我们制作一个适配器

public class TurkeyAdapter implements Duck {

    private Turkey turkey;

    public TurkeyAdapter(Turkey turkey) {
        this.turkey = turkey;
    }

    public void quack() {
        turkey.gobble();
    }

    public void fly() {
        turkey.fly();
        turkey.fly();
    }
}

我们创建一个测试类来说明适配的结果:

class Test { public static void main(String[] args){ Duck duck = new AKindDuck(); Turkey turkey = new WildTurkey(); Duck duckAdapter = new TurkeyAdapter(turkey); duck.quack(); duck.fly(); System.out.println(); turkey.gobble(); turkey.fly(); System.out.println(); duckAdapter.quack(); duckAdapter.fly(); } }

输出结果为:

A kind duck quack
A kind duck fly

wild gobble
wild run

wild gobble
wild run
wild run

外观模式

提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。
比如看电影需要很多步骤,而我们可以把这很多种步骤封装在一个接口中叫做watchMovie()提供给外界。结束电影封装为endMovie()提供给外界。如下所示:

public class Movie {

    public void watchMovie() {
        ActionA();
        ActionC();
    }

    public void endMovie() {
        ActionB();
        ActionD();
    }

    private void ActionA(){}
    private void ActionB(){}
    private void ActionC(){}
    private void ActionD(){}
}