装饰者模式理解

装饰模式(别名:包装器)
     动态地给对象添加一些额外的职责。就功能来说装饰模式相比生成子类更为灵活。



Decorator Pattern(Another Name: Wrapper) 

     Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.


一 、 概述


 装饰模式是动态地扩展一个对象的功能而不需要改变原始类代码的一种成熟模式。在装饰模式中,“具体组件”类和“具体装饰”类是该模式中的最重要的两个角色。


假设系统中有一个Bird抽象类以及Bird类的一个子类:Sparrow。Sparrow类实现了Bird类的fly方法,使得Sparrow类创建的对象调用fly方法能连续飞行100米。现在用户需要两种鸟,必须分别能连续飞行150米和200米。


二、装饰模式模式的结构与使用


装饰模式的结构中包括四种角色:


 抽象组件(Component) 


 具体组件(ConcreteComponent) 


 装饰(Decorator) 


 具体装饰(ConcreteDecotator)


dd

值得注意的是具体组件和抽象的装饰都泛化了component,后者之所以泛化主要是有相同的类型,并且装饰持有被装饰着【组件的引用】,两者是依赖关系

具体的装饰者还能附加新的方法,在原有的基础上进行扩充。


1.抽象组件 : Bird.java 
public abstract class Bird{
   public abstract int fly();
}

2.具体组件 : Sparrow.java 

public class Sparrow extends Bird{
   public final int DISTANCE=100;
   public int fly(){
      return DISTANCE;
   }
}

3.装饰 (Decorator): Decorator.java 

public abstract class Decorator extends Bird{
    protected Bird bird;
    public Decorator(){
    }
    public Decorator(Bird bird){
       this.bird=bird; 
    }
}

4.具体装饰(ConcreteDecotator): SparrowDecorator.java 

public class  SparrowDecorator extends Decorator{
   public final int DISTANCE=50;        //eleFly方法能飞50米
   SparrowDecorator(Bird bird){
      super(bird);
   }
   public int fly(){
      int distance=0;
      distance=bird.fly()+eleFly(); 
      return distance; 
   }
   private int eleFly(){              //装饰者新添加的方法
      return DISTANCE;
   }
} 

5.应用 Application.java
 public class Application{
   public void needBird(Bird bird){
       int flyDistance=bird.fly();
       System.out.println("这只鸟能飞行"+flyDistance +"米");  
   }
   public static void main(String args[]){
      Application client=new Application ();    
      Bird sparrow=new Sparrow();          
      Bird sparrowDecorator1=
      new SparrowDecorator(sparrow);       
      Bird sparrowDecorator2=
      new SparrowDecorator(sparrowDecorator1); 
      client.needBird(sparrowDecorator1); 
      client.needBird(sparrowDecorator2);                
  }
}

也许这里例子并不那么形象,我们思考一下,当我们喝咖啡的时候,咖啡作为一个组件,具体组件,有各种特色的咖啡,装饰者就好比各种调料,加奶,加糖。。


如果使用传统的继承方式实现,就是在原有的具体组件上添加成员吧,代码都是写死的我们利用装饰着模式可以动态的扩展,动态的再装饰,最关键的是对外仍然呈现原有的类

型还可以在原有的继承的行为进行进一步扩充。【一点点套】 缺点是子类太多


三、装饰模式的优点  


被装饰者和装饰者是松耦合关系。由于装饰(Decorator)仅仅依赖于抽象组件(Component)【依赖倒置原则】因此具体装饰只知道它要装饰的对象是抽

象组件的某一个子类的实例,但不需要知道是哪一个具体子类。


  装饰模式满足“开-闭原则”。不必修改具体组件,就可以增加新的针对该具体组件的具体装饰。
可以使用多个具体装饰来装饰具体组件的实例。



四.常见的应用


FileInputStream.java

import java.nio.channels.FileChannel;
import sun.nio.ch.FileChannelImpl;



public
class FileInputStream extends InputStream
{
   
    private FileDescriptor fd;

    private FileChannel channel = null;

    
    public FileInputStream(String name) throws FileNotFoundException {
        this(name != null ? new File(name) : null);
    }

          java.lang.SecurityManager#checkRead(java.lang.String)
    
    public FileInputStream(File file) throws FileNotFoundException {
	String name = (file != null ? file.getPath() : null);
	SecurityManager security = System.getSecurityManager();
	if (security != null) {
	    security.checkRead(name);
	}
        if (name == null) {
            throw new NullPointerException();
        }
	fd = new FileDescriptor();
	open(name);
    }

    
    public FileInputStream(FileDescriptor fdObj) {
	SecurityManager security = System.getSecurityManager();
	if (fdObj == null) {
	    throw new NullPointerException();
	}
	if (security != null) {
	    security.checkRead(fdObj);
	}
	fd = fdObj;
    }

   
    private native void open(String name) throws FileNotFoundException;

   
    public native int read() throws IOException;


   
    private native int readBytes(byte b[], int off, int len) throws IOException;//非Java实现

   

    public int read(byte b[]) throws IOException {
	return readBytes(b, 0, b.length);
    }

    
    public int read(byte b[], int off, int len) throws IOException {
	return readBytes(b, off, len);
    }

   
    public native long skip(long n) throws IOException;

    public native int available() throws IOException;

   
    public void close() throws IOException {
        if (channel != null)
            channel.close();
        close0();
    }

    
    public final FileDescriptor getFD() throws IOException {
	if (fd != null) return fd;
	throw new IOException();
    }

    
    public FileChannel getChannel() {
	synchronized (this) {
	    if (channel == null)
		channel = FileChannelImpl.open(fd, true, false, this);
	    return channel;
	}
    }

    private static native void initIDs();

    private native void close0() throws IOException;

    static {
	initIDs();
    }

   
    protected void finalize() throws IOException {
	if (fd != null) {
	    if (fd != fd.in) {
		close();
	    }
	}
    }
}

FilterInputStream.java

public
class FilterInputStream extends InputStream {
    
    protected volatile InputStream in;//持有引用对象

  
    protected FilterInputStream(InputStream in) {
	this.in = in;
    }

    public int read() throws IOException {
	return in.read();
    }

   
    public int read(byte b[]) throws IOException {
	return read(b, 0, b.length);
    }

  
    public int read(byte b[], int off, int len) throws IOException {
	return in.read(b, off, len);
    }

    public long skip(long n) throws IOException {
	return in.skip(n);
    }

  
    public int available() throws IOException {
	return in.available();
    }

  
    public void close() throws IOException {
	in.close();
    }

   
    public synchronized void mark(int readlimit) {
	in.mark(readlimit);
    }

    
    public synchronized void reset() throws IOException {
	in.reset();
    }

   
    public boolean markSupported() {
	return in.markSupported();
    }
}
通过这个类再派生了BufferedReader等类




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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值