设计模式-Python Java装饰者模式

装饰者模式定义

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

实现类图

    2013-1-3 星期四 22-08-13

装饰者模式的特点

 A 装饰者和被装饰对象有相同的超类型。(注意这是利用继承达到”类型匹配“,而不是利用继承获得”行为“,行为来自装饰者和基础组件,或者与其他装饰者之间的组合关系

 B   可以用一个或多个装饰者包装一个对象。

 C 因为装饰者和被装饰者具有相同的类型,所以任何需要原始对象的场合,可以用装饰过的对象代替。

 D 装饰者可以在所委托被装饰者的行为之前与/或之后,加上自己的行为,以达到特定的目的。

 E 对象可以在任何时候被装饰,所以可以在运行时动态地、不限量地用你喜欢的装饰者来装饰对象

装饰者模式实现例子

例子1

 
interface Widget { void draw(); }             // 1. "lowest common denominator"

class TextField implements Widget {           // 3. "Core" class with "isa" rel
   private int width, height;
   public TextField( int w, int h ) {
      width  = w;
      height = h;
   }
   public void draw() {
      System.out.println( "TextField: " + width + ", " + height );
}  }
                                                // 2. Second level base class
abstract class Decorator implements Widget {    //    with "isa" relationship
   private Widget wid;                          // 4. "hasa" relationship
   public Decorator( Widget w ) { wid = w; }
   public void draw()           { wid.draw(); } // 5. Delegation
}

class BorderDecorator extends Decorator {          // 6. Optional embellishment
   public BorderDecorator( Widget w ) {
      super( w );
   }
   public void draw() {
      super.draw();                                // 7. Delegate to base class
      System.out.println( "   BorderDecorator" );  //    and add extra stuff
}  }

class ScrollDecorator extends Decorator {          // 6. Optional embellishment
   public ScrollDecorator( Widget w ) {
      super( w );
   }
   public void draw() {
      super.draw();                                // 7. Delegate to base class
      System.out.println( "   ScrollDecorator" );  //    and add extra stuff
}  }
//装饰者可以在所委托被装饰者的行为之前或者之后,加上自己的行为,以达到特定的目的
public class DecoratorDemo {
   public static void main( String[] args ) {
      // 8. Client has the responsibility to compose desired configurations
      Widget aWidget = new BorderDecorator(
                          new BorderDecorator(
                             new ScrollDecorator(
                                new TextField( 80, 24 ))));
      aWidget.draw();
}  }

输出结果为:TextField: 80, 24
   ScrollDecorator
   BorderDecorator
   BorderDecorator

对比python装饰模式实现的一个类似程序

def bread(func):
    def wrapper():
        print "</''''''\>"
        func()
        print "<\______/>"
    return wrapper

def ingredients(func):
    def wrapper():
        print "#tomatoes#"
        func()
        print "~salad~"
    return wrapper

@bread
@ingredients
def sandwich(food="--ham--"):
    print food

if (__name__=="__main__"):
    sandwich()

例子2:编写自己的java  I/O装饰器,能够实现将文本中的大写字母转换成小写

    JAVA I/O类就是利用装饰者模式来实现诸多的读取方式,InputStream是装饰者中的抽象组件。FilterInputStream是一个抽象装饰者,LIneNumberInputStream是一个具体装饰者,加上了计算行数的能力,BufferInputStream是一个加上缓冲输入功能和readline()方法的具体装饰者


import java.io.*;

class LowerCaseInputStream extends FilterInputStream{
		public LowerCaseInputStream (InputStream in) {
			super(in);
		}
		//必须实现两个read方法 一个针对字节 一个针对字节数组
		public int read() throws IOException {
				int c = super.read();
				return (c == -1 ? c : Character.toLowerCase((char) (c)));
		}
		public int read(byte[] b,int offset,int len) throws IOException {
				int result = super.read(b, offset, len);
				for(int i =offset; i < offset + result ; i++){
						b[i] = (byte)Character.toLowerCase((char)b[i]);
				}
				return result;
		}
}
public class InputTest {
	public static void main(String[] args) {
			int c;
			try{
					InputStream in = new LowerCaseInputStream(
							new BufferedInputStream(
									new FileInputStream("test.txt") ) );
					while((c = in.read() ) >= 0) {
							System.out.print((char)c);
					}
					in.close();
			}catch (IOException e){
				e.printStackTrace();
			}
	}

3:编写实现不同种类咖啡加上不同配料的计价程序

//抽象组件饮料
abstract class Beverage {
	String description = "Unknown Beverage";
	public String getDescription() {
		return description;
	}
	public abstract double cost();
}
//具体组件 一种咖啡
 class Espresso extends Beverage {
	public Espresso() {
		description = "Espresso";
	}
	public double cost() {
		return 1.99;
	}
} 
class DarkRoast extends Beverage {
	public DarkRoast() {
		description = "Dark Roast Coffee";
	}
	public double cost() {
		return .99;
	}
}
class HouseBlend extends Beverage {
	public HouseBlend() {
		description = "House Blend Coffee";
	}
	public double cost() {
		return .89;
	}
}
//装饰者抽象类
public abstract class CondimentDecorator extends Beverage {
	public abstract String getDescription();
}
//具体装饰者牛奶
 class Milk extends CondimentDecorator {
	Beverage beverage;
	public Milk(Beverage beverage) {
		this.beverage = beverage;
	}
	public String getDescription() {
		return beverage.getDescription() + ", Milk";
	}
	public double cost() {
		return .10 + beverage.cost();
	}
}
//具体装饰者摩卡
 class Mocha extends CondimentDecorator {
	Beverage beverage;
	public Mocha(Beverage beverage) {
		this.beverage = beverage;
	}
	public String getDescription() {
		return beverage.getDescription() + ", Mocha";
	}
	public double cost() {
		return .20 + beverage.cost();
	}
}
//具体装饰者奶泡
 class Whip extends CondimentDecorator {
	Beverage beverage;
	public Whip(Beverage beverage) {
		this.beverage = beverage;
	}
	public String getDescription() {
		return beverage.getDescription() + ", Whip";
	}
	public double cost() {
		return .10 + beverage.cost();
	}
}
public class StarbuzzCoffee {
	public static void main(String args[]) {
		Beverage beverage = new Espresso();
		System.out.println(beverage.getDescription() 
				+ " $" + beverage.cost());
 
		Beverage beverage2 = new DarkRoast();
		beverage2 = new Mocha(beverage2);
		beverage2 = new Mocha(beverage2);
		beverage2 = new Whip(beverage2);
		System.out.println(beverage2.getDescription() 
				+ " $" + beverage2.cost());
 
		Beverage beverage3 = new HouseBlend();
		beverage3 = new Soy(beverage3);
		beverage3 = new Mocha(beverage3);
		beverage3 = new Whip(beverage3);
		System.out.println(beverage3.getDescription() 
				+ " $" + beverage3.cost());
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值