java设计模式系列-装饰者模式

定义:

装饰者模式:指的是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。

特点:

优点

1、装饰者和被装饰者继承或实现同一个装饰类或接口

2、装饰模式可以提供比继承更高的灵活性

3、可以通过一种动态的功能来扩展一个类的功能,在运行时选择不同的装饰器,从而实现不同的行为。

4、组合具体的装饰类,可以创建很多不同行为的组合。可以使用具体的装饰类来装饰同一个对象,获得功能更加强大的对象。

5、具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,在使用时再对其进行组合,原有代码无须改变,符合“开闭原则”。

缺点:

1、会产生很多的小对象,增加了系统的复杂

 2、这种比继承更加灵活机动的特性,也同时意味着装饰模式比继承更加易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐。

具体使用场景:

1、在java I/O流中的使用

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(new File("d:/text.txt"))));

这种对File类的包装,由内层到外层扩展输入流的功能,就是一个典型的装饰者模式。inputstream是被装饰对象,然后Fileinputstream、InputStream、BufferedReader都是它的装饰器,用来扩展它的功能!

2、在struts2框架中的使用

JavaEE API 中的 ServletRequestWrapper、HttpServletRequestWrapper 对于 ServletRequest 的封装 (Struts2 中的 StrutsRequestWrapper 对 HttpServletRequestWrapper 进行了继承扩展,对 ServletRequest 进一步封装,也属于装饰者模式的应用之一)

3、Android 中使用

对于 android 开发工程师来说,最最重要的就应该是“上帝类” Context 和其子类了


所以对于 Application,Activity 和 Service 等类来说,他们只是一个个装饰者,都是用来装饰 ContextImpl 这个被装饰者类,Application 是在 createBaseContextForActivity 方法中,通过 ContextImpl 的静态方法 createActivityContext 获得一个 ContextImpl 的实例对象,并通过 setOuterContext 方法将两者建立关联;Activity 是通过 handleLaunchActivity 方法设置的 ContextImpl 实例,这个方法会获取到一个Activity对象,在performLaunchActivity函数中会调用该activity的attach方法,这个方法把一个ContextImpl对象attach到了Activity中。

UML图理解:


装饰者模式共有四大角色:
Component:抽象组件
可以是一个接口或者是抽象类,其充当的就是被装饰的原始对象,用来定义装饰者和被装饰者的基本行为。

ConcreteComponent:组件具体实现类
该类是 Component 类的基本实现,也是我们装饰的具体对象。

Decorator:抽象装饰者
装饰组件对象,其内部一定要有一个指向组件对象的引用。在大多数情况下,该类为抽象类,需要根据不同的装饰逻辑实现不同的具体子类。当然,如果是装饰逻辑单一,只有一个的情况下我们可以忽略该类直接作为具体的装饰者。

ConcreteDecoratorA 和 ConcreteDecoratorB:装饰者具体实现类
对抽象装饰者的具体实现。

代码演示:

借助去麦当劳购买汉堡的例子,不同的客户有不同的需求,有的需要加青菜,有的需要加牛排等等,为了满足不同客户的需求,可以使用装饰者模式来实现。

汉堡基类(被装饰者):

package com.gcc.designmode.decorator;
/**
 * 汉堡基类(被装饰者)
 * @author gcc
 *
 */
public abstract class Humburger {
	protected String name;
	
	public String getName(){    
        return name;    
    }    
        
    public abstract double getPrice();  

}
被装饰者初始化:

package com.gcc.designmode.decorator;
/**
 * 被装饰者初始状态
 * @author gcc
 *
 */
public class ChickenBurger extends Humburger{

	
	public ChickenBurger() {
		name = "鸡腿堡";
	}
	@Override
	public double getPrice() {
		// TODO Auto-generated method stub
		return 10;
	}

}

装饰者:

package com.gcc.designmode.decorator;
/**
 * 配料的基类(装饰者)
 * @author gcc
 *
 */
public abstract class Condiment extends Humburger{

	 public abstract String getName(); 
}

装饰者实现类:

package com.gcc.designmode.decorator;
/**
 * 加生菜(装饰者实现第一层)
 * @author gcc
 *
 */
public class Lettuce extends Condiment{

	private Humburger humburger;
	public Lettuce(Humburger humburger) {
		this.humburger = humburger;
	}
	@Override
	public String getName() {
		
		return humburger.getName()+"加生菜";
	}
	@Override
	public double getPrice() {
		// TODO Auto-generated method stub
		return humburger.getPrice()+1.5;
	}
	
	
}

package com.gcc.designmode.decorator;
/**
 * 加辣椒(装饰者实现第二层)
 * @author gcc
 *
 */
public class Chilli extends Condiment{

	private Humburger humburger;
	
	public Chilli(Humburger humburger) {
		this.humburger = humburger;
	}

	@Override
	public String getName() {
		return humburger.getName()+"加辣椒";
	}

	@Override
	public double getPrice() {
		return humburger.getPrice();
	}

}

测试类:

package com.gcc.designmode.decorator;
/**
 * 测试类(购买汉堡)
 * @author gcc
 *
 */
public class Test {

	public static void main(String[] args) {
		Humburger humburger = new ChickenBurger();
		 System.out.println(humburger.getName()+"  价钱:"+humburger.getPrice());    
	     Lettuce lettuce = new Lettuce(humburger);    
	     System.out.println(lettuce.getName()+"  价钱:"+lettuce.getPrice());    
	     Chilli chilli = new Chilli(humburger);    
	     System.out.println(chilli.getName()+"  价钱:"+chilli.getPrice());    
	     Chilli chilli2 = new Chilli(lettuce);    
	     System.out.println(chilli2.getName()+"  价钱:"+chilli2.getPrice());    
	}
}

作者:scgyus(转载请说明出处)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值