揭秘设计模式:装饰模式(Decorator)的学习与理解

    链接地址:http://www.xx566.com/detail/125.html

    学习I/O的时候,各种putStream常常会困扰新手,这时候总会说:Java I/O设计的时候使用了装饰(Decorator)模式对各种Stream做了包装,到后来学习Struts2的时候也提到了装饰(Decorator) 模式 ,struts2对ServletRequest做了装饰 ,那么到底什么是装饰(Decorator)模式呢,我们今天就来学习一下。 

 

    我们首先来看一下装饰模式的官方定义:Attach additional responsibilities to an object dynamically keeping the same interface. Decorators provide a flexible alternative to subclassing for extending functionality.大概意思就是:对一个相同的接口动态的添加额外的功能,装饰器提供了一种灵活的子类扩展的功能。

 

    翻阅一些资料,里面的解释是:动态的给一个对象增加一些额外的职责。就增加功能来说,他比生成子类更加灵活。装饰模式以对客户端透明的方式扩展对象的功 能,是继承关系的一个替代方案,提供比继承更多的灵活性。动态给一个对象增加功能,这些功能可以再动态的撤消。增加由一些基本功能的排列组合而产生的非常 大量的功能。

 

    不太明白哈,我们来研究一下装饰模式的UML设计图:

    图中我们可以看到,在装饰模式中有四种角色:Component抽象构件,ConcreateComponent具体组件,Decorator抽象装饰角色,ConcreateDecorator具体抽象角色。

 

    说白了,其实装饰模式的核心就是理清楚Component与Decorator的关系,也就是能够分清主体类与装饰类,  wiki上关于装饰模式的讲解很详细,列举的例子也很典型,这里借用一下。

 

    比如说:购买coffee,先忽略coffee添加的成分,简单的原味coffee(里面有water)就是主体类,在装饰模式中,必然有一个最基本、最 核心、最原始的接口或抽象类充当Component抽象构件。不过有的顾客喜欢加糖的、加牛奶的等等,牛奶、糖是coffee里额外添加的成分,起着装饰 coffee的作用,就是装饰类。

    

    下面,我们通过代码,来深入理解装饰模式,首先我们抽象出一个coffee的主体,包含价格、成分,代码如下:

/**
 * 抽象主体类
 * User: Realfighter
 * Date: 2014/8/16
 * Time: 10:09
 */
public abstract class Coffee {
    abstract double costs(); //coffee价格
 
    abstract String contains();//coffee包含成分
}

    当然,我们可以先构建一个基本的coffee实体,包含water,价格1元,代码如下:

/**
 * 最基本的成分water
 * User: Realfighter
 * Date: 2014/8/16
 * Time: 10:28
 */
public class CoffeeOnlyWater extends Coffee {
    @Override
    public double costs() {
        return 1;
    }
 
    @Override
    public String contains() {
        return "water";
    }
}

    coffee主体好了,我们就需要根据客户的不同口味装饰成不同的coffee,首先我们抽象出一个coffee的装饰类,内部拥有coffee的引用,提供获取价格和成分的方法,代码如下:

/**
 * coffee装饰类
 * User: Realfighter
 * Date: 2014/8/16
 * Time: 10:30
 */
public abstract class CoffeeDecorator extends Coffee {
    protected final Coffee coffee;
 
    public CoffeeDecorator(Coffee coffee) {
        this.coffee = coffee;
    }
 
    public double costs() {
        return coffee.costs();
    }
 
    public String contains() {
        return coffee.contains();
    }
 
}

    有了装饰类的抽象,我们就需要实实在在的去装饰coffee了,我们有两种装饰的成分,milk和sugar,添加sugar的coffee要昂贵1元,milk的昂贵2元,并且需要给客户说明真实的价格和成分,代码如下:

/**
 * 装饰成分:糖sugar
 * User: Realfighter
 * Date: 2014/8/16
 * Time: 10:43
 */
public class CoffeeAddSugar extends CoffeeDecorator {
    public CoffeeAddSugar(Coffee coffee) {
        super(coffee);
    }
 
    @Override
    public double costs() {
        //sugar额外加1元
        return super.costs() + 1;
    }
 
    @Override
    public String contains() {
        return super.contains() + " sugar";
    }
}
/**
 * 装饰成分:牛奶milk
 * User: Realfighter
 * Date: 2014/8/16
 * Time: 10:41
 */
public class CoffeeAddMilk extends CoffeeDecorator {
    public CoffeeAddMilk(Coffee coffee) {
        super(coffee);
    }
 
    @Override
    public double costs() {
        //milk额外加2元
        return super.costs() + 2;
    }
 
    @Override
    public String contains() {
        return super.contains() + " milk";
    }
}

    好了,这样我们的公司就可以开张了,第一天来了三位顾客,在排队购买,第一个要了杯最普通的,第二位顾客在前者基础上加了milk牛奶,第三位顾客说要一杯和第二位顾客一样的,后来尝了尝,有点苦,另外加了点sugar糖,顺利营业了。

/**
 * 客户来购买coffee
 * User: Realfighter
 * Date: 2014/8/16
 * Time: 10:45
 */
public class Customer {
 
    /**
     * @param costs    价格
     * @param contains 成分
     */
    private static void print(int index, double costs, String contains) {
        System.out.println("customer " + index + " >>> coffee costs:" + costs + ",contains:" + contains);
    }
 
    public static void main(String[] args) {
        //第一杯coffee只是最基本的coffee
        Coffee coffee = new CoffeeOnlyWater();
        print(1, coffee.costs(), coffee.contains());
        //第二杯coffee在前者基础上加了milk
        coffee = new CoffeeAddMilk(coffee);
        print(2, coffee.costs(), coffee.contains());
        //第三杯coffee在第二杯基础上再加了sugar
        coffee = new CoffeeAddSugar(coffee);
        print(3, coffee.costs(), coffee.contains());
    }
}

    打印结果:

customer 1 >>>>> coffee costs: 1.0 ,contains:water
customer 2 >>>>> coffee costs: 3.0 ,contains:water milk
customer 3 >>>>> coffee costs: 4.0 ,contains:water milk sugar

你可能感兴趣的:(java,设计模式,Decorator,装饰模式)