java装饰者模式

装饰者模式:给一个对象增加一些新的功能,而且要求是动态的,要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例。

假如我们想对房子进行装饰,首先得有一个House接口,里面有装饰的方法,代表是装饰房子这样的一个通用的特性。

House接口:

public interface House {
	//刷墙漆
	public void paint();
	//贴墙纸
	public void wallpaper();
}
然后定义一个抽象的装饰类Decorator实现House接口,Decorator类:

public abstract class Decorator implements House {
	//持有被装饰对象引用
	private House house;
	public Decorator(House house){
		this.house = house;
	}
	
	@Override
	public void paint() {
		house.paint();
	}

	@Override
	public void wallpaper() {
		house.wallpaper();
	}
}
接下来就会有三个人分别来装饰房子,他们都要继承抽象的装饰类Decorator。

PersonOne类:

public class PersonOne extends Decorator {
	public PersonOne(House house) {
		super(house);
	}

	@Override
	public void paint() {
		super.paint();
		System.out.println("选购墙漆");
	}
	@Override
	public void wallpaper() {
		super.wallpaper();
		System.out.println("选购墙纸");
	}
}

PersonTwo类:

public class PersonTwo extends Decorator {
	public PersonTwo(House house) {
		super(house);
	}

	@Override
	public void paint() {
		super.paint();
		System.out.println("墙漆的用量勾兑,搅匀");
	}

	@Override
	public void wallpaper() {
		super.wallpaper();
		System.out.println("剪裁墙纸");
	}
}

PersonThree类:

public class PersonThree extends Decorator{
	public PersonThree(House house) {
		super(house);
	}

	@Override
	public void paint() {
		super.paint();
		System.out.println("开始刷墙漆");
	}

	@Override
	public void wallpaper() {
		super.wallpaper();
		System.out.println("开始贴墙纸");
	}
}

三个人要做的工作都已经安排好了,现在我们要选择一个房间来装饰,就选卧室吧

BedRoom类:

public class BedRoom implements House {
	@Override
	public void paint() {
		System.out.println("我要装饰卧室,打算刷点墙漆");
	}

	@Override
	public void wallpaper() {
		System.out.println("---------感觉还不太满意");
		System.out.println("我还打算贴点墙纸");
	}
}


房间也选好了,开始动工吧。

DecoratorTest类:

public class DecoratorTest {
	public static void main(String[] args) {
		House house = new BedRoom();
		Decorator decorator = new PersonThree(new PersonTwo(new PersonOne(house)));
		decorator.paint();
        decorator.wallpaper();
	}
}

输出结果:我要装饰卧室,打算刷点墙漆
                    选购墙漆
                     墙漆的用量勾兑,搅匀
                     开始刷墙漆
                     ---------感觉还不太满意
                    我还打算贴点墙纸
                    选购墙纸
                    剪裁墙纸
                    开始贴墙纸

这样房间就算装饰完了,大功告成。

其实装饰者模式在java中运用很广泛的,比如IO流中,运用了大量的装饰者模式。以InputStream为例,从装饰者模式来看下InputStream的结构。

InputStream的类图关系 
class java.lang.Object 

|—class java.io.InputStream //输入流,字节形式,为以下的基类 
| | 
| |——java.io.ByteArrayInputStream //从字节数组中读取 
| | 
| |——java.io.FileInputStream //从文件中读取数据 
| | 
| |—— java.io.FileInputStream //过滤流的基类, 
| | | // 过滤可以了解为各种处理技术的形象称呼 
| | | 
| | |——java.io.BufferedInputStream //缓冲技术,数据来自底层输入流 
| | | 

| | |——java.util.zip.CheckedInputStream //用于维护数据校验和

| | |

| | |——javax.crypto.CipherInputStream //属于Cipher类的扩展,称为密钥流

| | | 
| | |——java.io.DataInputStream //可读java数据类型 
| | | 

| | |——java.util.zip.DeflaterInputStream //压缩数据的输入流 
| | | 

| | |——java.security.DigestInputStream //消息摘要输入流,可以通过读取输入流的方式完成摘要更新 
| | | 

| | |——java.util.zip.InflaterInputStream //解压缩 "deflate" 压缩格式的数据实现流过滤器。它还用作其他解压缩过滤器(如 GZIPInputStream)的基础。

| | | 

| | |——java.io.LineNumberInputStream //输入流过滤器,提供当前行号的附加功能(已过时)

| | | 

| | |——javax.swing.ProgressMonitorInputStream  //监视读取某些 InputStream 的进度 
| | |

| | |——java.io.PushbackInputStream //允许我们试探性的读取数据流,如果不是我们想要的则返还回去,之所以能够这样,因为其内部维护了一个pushback buffer缓冲区。 

| | | 
| | |——java.util.zip.GZIPInputStream //继承InflaterInputStream,读取 GZIP 文件格式的压缩数据实现流过滤器
| | | 
| |—— ....... 

从以上可以看出,InputStream就是装饰者模式中的超类(Component),ByteArrayInputStream、FileInputStream相当于被装饰者(ConcreteComponent),这些类都提供了最基本的字节读取功能。而另外一个和这两个类是同一级的FilterInputStream即是装饰者(Decorator),BufferedInputStream、DataInputStream、PushbackInputStream......这些都是被装饰者装饰后形成的成品。

根据装饰者模式的特点,我们可以总结出这些IO流的使用方法:

File file = new File ("test.txt"); 
FileInputStream in=new FileInputStream(file); 
BufferedInputStream inBuffered=new BufferedInputStream (in); 
这里的 BufferedInputStream主要是提供了缓存机制,先读入一个byte[],等count到达缓存Byte[]的大小的时候,再一次读入。你也可以写成:

BufferedInputStream inBuffered = new BufferedInputStream (new FileInputStream(new File ("test.txt")));
从使用者的角度来看装饰者模式,可以看出它的一个缺点:装饰者模式的实现对于使用者是透明的。






  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
装饰者模式是一种结构型设计模式,它许在不改变原有对象的情况下,动态地将新功能添加到对象上。在Java中,装饰者模式常用于扩展或修改现有类的功能,同时保持代码的灵活性和可扩展性。 在装饰者模式中,有以下几个角色: 1. 抽象组件(Component):定义了被装饰对象和装饰对象的共同接口。 2. 具体组件(ConcreteComponent):实现了抽象组件接口,是被装饰的对象。 3. 抽象装饰者(Decorator):继承了抽象组件接口,并持有一个抽象组件对象的引用。 4. 具体装饰者(ConcreteDecorator):实现了抽象装饰者接口,负责对具体组件进行装饰。 下面是一个简单的示例,展示了如何使用装饰者模式来扩展一个咖啡店的咖啡功能: ```java // 抽象组件 interface Coffee { String getDescription(); double getCost(); } // 具体组件 class SimpleCoffee implements Coffee { @Override public String getDescription() { return "Simple Coffee"; } @Override public double getCost() { return 1.0; } } // 抽象装饰者 abstract class CoffeeDecorator implements Coffee { protected Coffee decoratedCoffee; public CoffeeDecorator(Coffee decoratedCoffee) { this.decoratedCoffee = decoratedCoffee; } @Override public String getDescription() { return decoratedCoffee.getDescription(); } @Override public double getCost() { return decoratedCoffee.getCost(); } } // 具体装饰者 class MilkDecorator extends CoffeeDecorator { public MilkDecorator(Coffee decoratedCoffee) { super(decoratedCoffee); } @Override public String getDescription() { return super.getDescription() + ", with Milk"; } @Override public double getCost() { return super.getCost() + 0.5; } } class SugarDecorator extends CoffeeDecorator { public SugarDecorator(Coffee decoratedCoffee) { super(decoratedCoffee); } @Override public String getDescription() { return super.getDescription() + ", with Sugar"; } @Override public double getCost() { return super.getCost() + 0.3; } } public class Main { public static void main(String[] args) { // 创建一个简单咖啡对象 Coffee coffee = new SimpleCoffee(); System.out.println(coffee.getDescription() + " $" + coffee.getCost()); // 使用装饰者来添加牛奶和糖 Coffee coffeeWithMilkAndSugar = new SugarDecorator(new MilkDecorator(coffee)); System.out.println(coffeeWithMilkAndSugar.getDescription() + " $" + coffeeWithMilkAndSugar.getCost()); } } ``` 输出结果: ``` Simple Coffee $1.0 Simple Coffee, with Milk, with Sugar $1.8 ``` 在上述示例中,我们定义了一个抽象组件 `Coffee`,具体组件 `SimpleCoffee` 实现了抽象组件接口。然后,我们定义了抽象装饰者 `CoffeeDecorator`,它持有一个抽象组件对象的引用,并实现了抽象组件接口。具体装饰者 `MilkDecorator` 和 `SugarDecorator` 继承了抽象装饰者,并在其基础上添加了额外的功能。 在 `Main` 类中,我们首先创建了一个简单咖啡对象,并输出其描述和价格。然后,我们使用装饰者模式来添加牛奶和糖,并输出装饰后的咖啡描述和价格。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值