码迷,mamicode.com
首页 > 其他好文 > 详细

装饰模式

时间:2015-08-20 12:08:12      阅读:179      评论:0      收藏:0      [点我收藏+]

标签:

装饰模式又名包装模式。装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。

装饰模式以对客户端透明的方式动态的给一个对象附加上更多的责任。换言之,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。

装饰模式的关键在于这种功能的扩展是透明的。

装饰模式的各个角色有:

  • 抽象构件(Component)角色:给出一个抽象接口,以规范准备接收附加责任的对象。
  • 具体构件(Concrete Component)角色:定义一个将要接收附加责任的类。
  • 装饰(Decorator)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。
  • 具体装饰(Concrete Decorator)角色:负责给构件对象“贴上”附加的责任。

在以下情况下应当使用装饰模式:

  1. 需要扩展一个类的功能,或给一个类增加附加责任。
  2. 需要动态地给一个对象增加功能,这些功能可以再动态的撤销。
  3. 需要增加一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变得不现实。

下面看一个具体的例子,发票系统:

需求:

有一个电子销售系统需要打印出顾客所购买的商品的发票。一张发票可以分为三个部分:

  • 发票头部(Header):上面有顾客的名字,销售的日期。
  • 发票主部:销售的货物清单,包括商品名字、购买的数量、单价、小计。
  • 发票的尾部(Footer):商品总金额。

下面就是要求打印出的发票的大致样子:

技术分享

其中,发票的头部和尾部可以有很多种可能的格式,因此系统的设计必须给出足够的灵活性,使得一个新的头部和尾部格式能够较为容易地插入到系统中;同时本系统的客户端必须可以随意地选择某一个头部格式和某一个尾部格式的组合并与主部格式组合起来。

在这个系统里使用装饰模式,那么发票的头部和尾部都可以分别由具体装饰类来代表。有多少种头部和尾部,就可以有多少种相应的具体装饰类。

/**
 * 抽象构件角色实现
 */
public abstract class Order
{
    protected String customerName;
    protected Date salesDate;
    protected Vector<OrderLine> items=new Vector<OrderLine>();
    public void print()
    {
        for(int i=0;i<items.size();i++)
        {
            OrderLine item=items.get(i);
            item.printLine();
        }
    }

    public String getCustomerName() {
        return customerName;
    }

    public void setCustomerName(String customerName) {
        this.customerName = customerName;
    }

    public Date getSalesDate() {
        return salesDate;
    }

    public void setSalesDate(Date salesDate) {
        this.salesDate = salesDate;
    }
    public void addItem(OrderLine item)
    {
        items.add(item);
    }
    public void remoteItem(OrderLine item)
    {
        items.remove(item);
    }
    public double getGrandTotal()
    {
        double amnt=0.0D;
        for(int i=0;i<items.size();i++)
        {
            OrderLine item=items.get(i);
            amnt+=item.getSubtotal();
        }
        return amnt;
    }
    protected String formatCurrency(double amnt)
    {
        return NumberFormat.getCurrencyInstance().format(amnt);
    }
}

 

/**
 * 具体构件角色
 */
public class SalesOrder extends Order
{
    public SalesOrder()
    {

    }
    public void print()
    {
        super.print();
    }

}

 

/**
 * 抽象装饰角色
 */
public class OrderDecorator extends Order
{
    //抽象装饰角色,持有一个将要附加责任的类
    protected Order order;
    public OrderDecorator(Order order)
    {
        this.order=order;
        this.setSalesDate(order.getSalesDate());
        this.setCustomerName(order.getCustomerName());
    }
    public void print()
    {
        super.print();
    }
}

 

/**
 * 具体装饰角色
 */
public class HeaderDecorator extends OrderDecorator
{
    public HeaderDecorator(Order anOrder)
    {
        super(anOrder);
    }
    public void print()
    {
        this.printHeader();
        super.order.print();
    }
    private void printHeader()
    {
        System.out.println("***\tINVOICE\t***");
        System.out.println("XYZ Incorporated\nDate of Sale:");
        System.out.println(order.getSalesDate());
        System.out.println("===========================");
        System.out.println("Item\t\tUnits\tUnit Price\tSubtotal");
    }

}

 

/**
 * 具体装饰角色
 */
public class FooterDecorator extends OrderDecorator {
    public FooterDecorator(Order anOrder)
    {
        super(anOrder);
    }
    public void print()
    {
        super.order.print();
        printFooter();
    }
    public void printFooter()
    {
        System.out.println("===========================");
        System.out.println("Total\t\t\t\t\t\t"+formatCurrency(order.getGrandTotal()));
    }
}

 

/**
 * OrderLine类是一个销售单的购物清单中的一行
 */
public class OrderLine
{
    private String itemName;
    private int units;
    private double unitPrice;
    public void printLine()
    {
        System.out.println(itemName+"\t\t"+units+"\t\t"+formatCurrency(unitPrice)+"\t\t"+formatCurrency(getSubtotal()));

    }
    public double getSubtotal()
    {
        return unitPrice * units;
    }
    private String formatCurrency(double amnt)
    {
        return NumberFormat.getCurrencyInstance().format(amnt);
    }

    public String getItemName() {
        return itemName;
    }

    public void setItemName(String itemName) {
        this.itemName = itemName;
    }

    public int getUnits() {
        return units;
    }

    public void setUnits(int units) {
        this.units = units;
    }

    public double getUnitPrice() {
        return unitPrice;
    }

    public void setUnitPrice(double unitPrice) {
        this.unitPrice = unitPrice;
    }
}

 

/**
 * 示意性的客户端源代码
 */
public class Client
{
    private static Order order;

    public static void main(String[] args) {
        order=new SalesOrder();
        order.setSalesDate(new Date());
        order.setCustomerName("XYZ Repair Shop");
        OrderLine line1=new OrderLine();
        line1.setItemName("wire");
        line1.setUnitPrice(154.23);
        line1.setUnits(4);
        order.addItem(line1);
        OrderLine line2=new OrderLine();
        line2.setItemName("iphone");
        line2.setUnitPrice(1499);
        line2.setUnits(1);
        order.addItem(line2);
        order=new HeaderDecorator(new FooterDecorator(order));
        order.print();
    }

}

 

装饰模式

标签:

原文地址:http://www.cnblogs.com/xtsylc/p/4744330.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!