說明:
裝飾模式是在不必改變原類文件和使用繼承的情況下,動態的擴展一個對象的功能。它是通過創建一個包裝對象,也就是裝飾來包裹真實的對象。裝飾模式的特點;
(1) 裝飾對象和真實對象有相同的接口。這樣客戶端對象就可以以和真實對象相同的方式和裝飾對象交互。
(2) 裝飾對象包含一個真實對象的索引(reference)
(3) 裝飾對象接受所有的來自客戶端的請求。它把這些請求轉發給真實的對象。
(4) 裝飾對象可以在轉發這些請求以前或以后增加一些附加功能。這樣就確保了在運行時,不用修改給定對象的結構就可以在外部增加附加的功能。在面向對象的設計中,通常是通過繼承來實現對給定類的功能擴展。
下表格列舉了裝飾模式和繼承的不同:
裝飾模式 VS 繼承
裝飾模式 繼承用來擴展特定對象的功能 用來擴展一類對象的功能
不需要子類 需要子類
動態地 靜態地
運行時分配職責 編譯時分派職責
防止由于子類而導致的復雜和混亂 導致很多子類產生,在一些場合,報漏類的層次
更多的靈活性 缺乏靈活性
對于一個給定的對象,同時可能有不同的裝飾對象,客戶端可以通過它的需要選擇合適的裝飾對象發送消息。 對于所有可能的聯合,客戶期望
很容易增加任何的 困難
給個實例,打印發票
package Decorator.printorder;
import java.text.NumberFormat;
public class OrderLine {
?private String itemName;
?private int units;
?private double unitPrice;
?
?public String getItemName() {
??return itemName;
?}
?
?public void setItemName(String itemName) {
??this.itemName = itemName;
?}
?
?public double getUnitPrice() {
??return unitPrice;
?}
?
?public void setUnitPrice(double unitPrice) {
??this.unitPrice = unitPrice;
?}
?
?public int getUnits() {
??return units;
?}
?
?public void setUnits(int units) {
??this.units = units;
?}
?
?public void printLine(){
??System.out.println(itemName + "\t" + units
????+ "\t" + formatCurrency(unitPrice)
????+ "\t\t" + formatCurrency(getSubtotal()));
?}
?
?public double getSubtotal(){
??return units * unitPrice;
?}
?
?private String formatCurrency(double amnt){
??return NumberFormat.getCurrencyInstance().format(amnt);
?}
}
package Decorator.printorder;
?private int units;
?private double unitPrice;
?
?public String getItemName() {
??return itemName;
?}
?
?public void setItemName(String itemName) {
??this.itemName = itemName;
?}
?
?public double getUnitPrice() {
??return unitPrice;
?}
?
?public void setUnitPrice(double unitPrice) {
??this.unitPrice = unitPrice;
?}
?
?public int getUnits() {
??return units;
?}
?
?public void setUnits(int units) {
??this.units = units;
?}
?
?public void printLine(){
??System.out.println(itemName + "\t" + units
????+ "\t" + formatCurrency(unitPrice)
????+ "\t\t" + formatCurrency(getSubtotal()));
?}
?
?public double getSubtotal(){
??return units * unitPrice;
?}
?
?private String formatCurrency(double amnt){
??return NumberFormat.getCurrencyInstance().format(amnt);
?}
}
package Decorator.printorder;
import java.text.NumberFormat;
import java.util.Date;
import java.util.Vector;
import java.util.Date;
import java.util.Vector;
abstract public class Order {
?
?private OrderLine lnkOrderLine;
?protected String customerName;
?protected Date salesDate;
?protected Vector items = new Vector(10);
?
?public void print(){
??for(int i=0; i<items.size(); i++){
???OrderLine item = (OrderLine) items.get(i);
???item.printLine();
??}
?}
?
?private OrderLine lnkOrderLine;
?protected String customerName;
?protected Date salesDate;
?protected Vector items = new Vector(10);
?
?public void print(){
??for(int i=0; i<items.size(); i++){
???OrderLine item = (OrderLine) items.get(i);
???item.printLine();
??}
?}
?public String getCustomerName() {
??return customerName;
?}
??return customerName;
?}
?public void setCustomerName(String customerName) {
??this.customerName = customerName;
?}
??this.customerName = customerName;
?}
?public Date getSalesDate() {
??return salesDate;
?}
??return salesDate;
?}
?public void setSalesDate(Date salesDate) {
??this.salesDate = salesDate;
?}
?
?public void addItem(OrderLine item){
??items.add(item);
?}
?
?public void remove(OrderLine item){
??items.remove(item);
?}
?
?public double getGrandTotal(){
??double amnt = 0.0D;
??for(int i=0; i<items.size(); i++){
???OrderLine item = (OrderLine) items.get(i);
???amnt += item.getSubtotal();
??}
??return amnt;
?}
?
?protected String formatCurrency(double amnt){
??return NumberFormat.getCurrencyInstance().format(amnt);
?}
}
package Decorator.printorder;
??this.salesDate = salesDate;
?}
?
?public void addItem(OrderLine item){
??items.add(item);
?}
?
?public void remove(OrderLine item){
??items.remove(item);
?}
?
?public double getGrandTotal(){
??double amnt = 0.0D;
??for(int i=0; i<items.size(); i++){
???OrderLine item = (OrderLine) items.get(i);
???amnt += item.getSubtotal();
??}
??return amnt;
?}
?
?protected String formatCurrency(double amnt){
??return NumberFormat.getCurrencyInstance().format(amnt);
?}
}
package Decorator.printorder;
public class SalesOrder extends Order {
?public SalesOrder() {
??super();
??// TODO Auto-generated constructor stub
?}
??super();
??// TODO Auto-generated constructor stub
?}
?public void print() {
??// TODO Auto-generated method stub
??super.print();
?}
?
}
package Decorator.printorder;
??// TODO Auto-generated method stub
??super.print();
?}
?
}
package Decorator.printorder;
public abstract class OrderDecorator extends Order{
?protected Order order;
?
?public OrderDecorator(Order order){
??this.order = order;
??this.setSalesDate(this.order.getSalesDate());
??this.setCustomerName(this.order.getCustomerName());
?}
}
package Decorator.printorder;
?
?public OrderDecorator(Order order){
??this.order = order;
??this.setSalesDate(this.order.getSalesDate());
??this.setCustomerName(this.order.getCustomerName());
?}
}
package Decorator.printorder;
public class HeaderDecorator extends OrderDecorator {
?public HeaderDecorator(Order order) {
??super(order);
??// TODO Auto-generated constructor stub
?}
??super(order);
??// TODO Auto-generated constructor stub
?}
?public void print(){
??this.printHeader();
??super.order.print();
?}
?
?private void printHeader(){
??System.out.println("\t***\tI N V O I C E\t***\nXYZ Incorporated\nDate of Sale: "
????+ order.getSalesDate());
??????? System.out.println("========================================================");
??????? System.out.println("Item\t\tUnits\tUnit Price\tSubtotal");
?}
}
package Decorator.printorder;
??this.printHeader();
??super.order.print();
?}
?
?private void printHeader(){
??System.out.println("\t***\tI N V O I C E\t***\nXYZ Incorporated\nDate of Sale: "
????+ order.getSalesDate());
??????? System.out.println("========================================================");
??????? System.out.println("Item\t\tUnits\tUnit Price\tSubtotal");
?}
}
package Decorator.printorder;
public class FooterDecorator extends OrderDecorator {
?public FooterDecorator(Order order) {
??super(order);
??// TODO Auto-generated constructor stub
?}
??super(order);
??// TODO Auto-generated constructor stub
?}
?public void print(){
??super.order.print();
??printFooter();
?}
?
?private void printFooter(){
??????? System.out.println("========================================================");
??????? System.out.println("Total\t\t\t\t\t" +
??????????? formatCurrency(super.order.getGrandTotal()));
?}
}
package Decorator.printorder;
??super.order.print();
??printFooter();
?}
?
?private void printFooter(){
??????? System.out.println("========================================================");
??????? System.out.println("Total\t\t\t\t\t" +
??????????? formatCurrency(super.order.getGrandTotal()));
?}
}
package Decorator.printorder;
import java.util.Date;
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();
?
?public static void main(String[] args){
??order = new SalesOrder();
??order.setSalesDate(new Date());
??order.setCustomerName("XYZ Repair Shop");
??
??????? OrderLine line1 = new OrderLine();
??????? line1.setItemName("FireWheel Tire");
??????? line1.setUnitPrice(154.23);
??????? line1.setUnits(4);
??????? line1.setUnitPrice(154.23);
??????? line1.setUnits(4);
??????? order.addItem(line1);
??????? OrderLine line2 = new OrderLine();
??????? line2.setItemName("Front Fender");
??????? line2.setUnitPrice(300.45);
??????? line2.setUnits(1);
??????? line2.setUnitPrice(300.45);
??????? line2.setUnits(1);
??????? order.addItem(line2);
???????
??????? order = new HeaderDecorator(new FooterDecorator(order));
???????
??????? order.print();
???????
?}
}
???????
??????? order = new HeaderDecorator(new FooterDecorator(order));
???????
??????? order.print();
???????
?}
}