《JAVA与模式》之装修者模式

装饰者模式

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

具体被装饰者和抽象装饰类都继承于抽象被装饰者类,继承的是类型,而不是行为。行为来自装饰者和基础组件,或与其他装饰者之间的组合关系。

装饰模式的角色

  抽象构件角色(Component):给出一个抽象接口,以规范准备接收附加责任的对象。

  具体构件角色(Concrete Component):定义将要接收附加责任的类。

  装饰角色(Decorator):持有一个构件(Component)对象的引用,并定义一个与抽象构件接口一致的接口。

  具体装饰角色(Concrete Decorator):负责给构件对象“贴上”附加的责任。

装饰模式的特点

  装饰对象和真实对象有相同的接口。这样客户端对象就可以以和真实对象相同的方式和装饰对象交互。

  装饰对象包含一个真实对象的引用(reference)。

  装饰对象接收所有来自客户端的请求,它把这些请求转发给真实的对象。

  装饰对象可以在转发这些请求之前或之后附加一些功能。

  这样就确保了在运行时,不用修改给定对象的结构就可以在外部增加附加的功能。

代码

 1 public class Zhuangxiuzhe {
 2     public static void main(String[] args) {
 3         Zhuangxiuzhe zhuangxiuzhe=new Zhuangxiuzhe();
 4         Component component=zhuangxiuzhe.new ConcreteComponent();
 5         Component decorator=zhuangxiuzhe.new ConcreteDecorator1(component);
 6         decorator.doMethod();
 7         Component decorator2=zhuangxiuzhe.new ConcreteDecorator2(decorator);
 8         decorator2.doMethod();
 9
10     }
11
12     interface Component {
13
14         public void doMethod();
15
16     }
17
18     class ConcreteComponent implements Component {
19
20         public void doMethod() {
21             System.out.println("一般操作");
22
23         }
24
25     }
26     abstract class  Decorator implements Component{
27
28         protected Component component;
29         public Decorator(Component component){
30             this.component=component;
31         }
32
33
34     }
35     class ConcreteDecorator1 extends Decorator{
36
37         public ConcreteDecorator1(Component component) {
38             super(component);
39
40         }
41         public void test1(){
42             System.out.println("ConcreteDecorator1 额外操作");
43         }
44
45         public void doMethod() {
46             super.component.doMethod();
47             test1();
48         }
49     }
50     class ConcreteDecorator2 extends Decorator{
51
52         public ConcreteDecorator2(Component component) {
53             super(component);
54
55         }
56
57         public void doMethod() {
58             super.component.doMethod();
59             test2();
60         }
61
62         public void test2(){
63             System.out.println("ConcreteDecorator2 额外操作");
64         }
65     }
66
67
68 }

执行结果

一般操作
ConcreteDecorator1 额外操作
一般操作
ConcreteDecorator1 额外操作
ConcreteDecorator2 额外操作


突然发现装修者模式跟责任链模式有点相同,自身都引用了抽象类,这样可以调用传入的包装类

区别在于功能上:责任链强调的是请求由谁来处理,而装修者模式则是对引入的对象的现有功能进行包装,增强改变

Java IO中的装饰模式

  在IO中,具体构件角色是节点流,装饰角色是过滤流

  FilterInputStream和FilterOutputStream是装饰角色,而其他派生自它们的类则是具体装饰角色。

我们来看看代码

抽象角色类InputStream

1 public abstract class InputStream implements Closeable {
2
3
4 //实现了read等方法
5 public int read(byte b[]) throws IOException {
6     return read(b, 0, b.length);
7     }
8
9 }

具体角色类FileInputStream

1 public
2 class FileInputStream extends InputStream{
3
4
5 }

抽象包装类FilterInputStream

 1 public
 2 class FilterInputStream extends InputStream {
 3     /**
 4      * The input stream to be filtered.
 5      */
 6     protected volatile InputStream in;
 7
 8
 9 protected FilterInputStream(InputStream in) {
10     this.in = in;
11     }
12
13  public int read() throws IOException {
14     return in.read();
15     }
16
17
18 }

具体包装类BufferedInputStream

 1 public
 2 class BufferedInputStream extends FilterInputStream {
 3
 4 public BufferedInputStream(InputStream in) {
 5     this(in, defaultBufferSize);
 6     }
 7
 8 //完成了设置抽象角色类的映射
 9  public BufferedInputStream(InputStream in, int size) {
10     super(in);
11         if (size <= 0) {
12             throw new IllegalArgumentException("Buffer size <= 0");
13         }
14     buf = new byte[size];
15     }
16
17 //read方法中调用fill()
18  public synchronized int read() throws IOException {
19     if (pos >= count) {
20         fill();
21         if (pos >= count)
22         return -1;
23     }
24     return getBufIfOpen()[pos++] & 0xff;
25     }
26  private void fill() throws IOException {
27         byte[] buffer = getBufIfOpen();
28     if (markpos < 0)
29         pos = 0;        /* no mark: throw away the buffer */
30     else if (pos >= buffer.length)    /* no room left in buffer */
31         if (markpos > 0) {    /* can throw away early part of the buffer */
32         int sz = pos - markpos;
33         System.arraycopy(buffer, markpos, buffer, 0, sz);
34         pos = sz;
35         markpos = 0;
36         } else if (buffer.length >= marklimit) {
37         markpos = -1;    /* buffer got too big, invalidate mark */
38         pos = 0;    /* drop buffer contents */
39         } else {        /* grow buffer */
40         int nsz = pos * 2;
41         if (nsz > marklimit)
42             nsz = marklimit;
43         byte nbuf[] = new byte[nsz];
44         System.arraycopy(buffer, 0, nbuf, 0, pos);
45                 if (!bufUpdater.compareAndSet(this, buffer, nbuf)) {
46                     // Can‘t replace buf if there was an async close.
47                     // Note: This would need to be changed if fill()
48                     // is ever made accessible to multiple threads.
49                     // But for now, the only way CAS can fail is via close.
50                     // assert buf == null;
51                     throw new IOException("Stream closed");
52                 }
53                 buffer = nbuf;
54         }
55         count = pos;
56     int n = getInIfOpen().read(buffer, pos, buffer.length - pos);
57         if (n > 0)
58             count = n + pos;
59     }
60
61
62 }

fill()方法中除了自身操作外,我们看到了 int n = getInIfOpen().read(buffer, pos, buffer.length - pos);

1  private InputStream getInIfOpen() throws IOException {
2         InputStream input = in;
3     if (input == null)
4         throw new IOException("Stream closed");
5         return input;
6     }

在看看getInIfOpen()方法,我们就明白了 整个的过程

参考地址:

http://www.cnblogs.com/mengdd/archive/2013/02/12/2910302.html

http://blog.csdn.net/cai1213/article/details/8003445

http://xubindehao.iteye.com/blog/474636

《JAVA与模式》之装修者模式

时间: 2024-09-27 10:24:16

《JAVA与模式》之装修者模式的相关文章

《JAVA与模式》之建造者模式

1.概念 将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示. [构建与表示分离,同构建不同表示] 与抽象工厂的区别:在建造者模式里,有个指导者,由指导者来管理建造者,用户是与指导者联系的,指导者联系建造者最后得到产品. 消费者最后是通过建造者得到产品而不是通过指导者,另外,消费者无法直接让建造者建造产品,这个可能是建造者跟工厂方法的最大区别 工厂方法是需求者可以直接接触到工厂对象,然后指派其生产. 建造模式是将复杂的内部创建封装在内部,对于外部调用的人来说,只需要传入建造者和

Java设计模式(十) 备忘录模式 状态模式

(十九)备忘录模式 备忘录模式目的是保存一个对象的某个状态,在适当的时候恢复这个对象. class Memento{ private String value; public Memento(String value){ this.value = value; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } } class Storage

JAVA的模式对话框和非模式对话框

周末的时候,一位网友让我帮他把他的无模式对话框改成有模式对话框. 界面是有swing制作的,都是JFrame,我从来没有接触过swing编程.大致的代码还是看的懂,很多都和C#很相似. 然后就去查资料,JAVA的模式对话框是如何调用的.终于查到了需要用到JDialog类,JDialog的构造函数里可以指定是否是模式对话框. 1 public JDialog(Frame owner, String title, boolean modal) { 2 super(owner == null? Swi

Java设计模式3:工厂方法模式

工厂方法模式 工厂方法模式是类的创建模式.工厂方法模式的用意是定义一个创建产品对象的工厂接口,将实际创建工厂推迟到子类中. 工厂方法模式 工厂方法模式是对简单工厂模式进一步抽象的结果. 假如是不使用反射的工厂方法模式,那么所有的if... else if...else都放在工厂类中,势必造成工厂类的无限臃肿 这时候就需要工厂方法模式来处理这个问题了.工厂方法模式中,核心的工厂类不再负责所有对象的创建,而是将具体的创建工作交给子类去做.这个类则摇身一变变成了一个抽象工厂角色,仅仅负责给出具体工厂子

ctrl+z的JAVA实现,借助了命令模式(command pattern)

前些天学习<<JAVA与模式>>,到命令模式时,随带给了一个CTRL+Z案例的实现,想来学习编程这么久,CTRL+Z还没有认真实现过. 因此,借助JAVA与模式里面的源代码,自己对撤销和回退进行了实现(JAVA与模式书中代码有部分问题).此次用到了命令模式,因为有界面,有按钮,有接收者,有发送者. 以下是类图,只为方便,未考虑UML细节规范. 以下是程序的实现. MainFrame类:提供Main方法,Client类:类似于看电视的人,这里关联了UndoableTextArea,I

Java设计模式(五)外观模式 桥梁模式

(九)外观模式 外观模式为子系统提供一个接口,便于使用.解决了类与类之间关系的,外观模式将类之间的关系放在一个 Facade 类中,降低了类类之间的耦合度,该模式不涉及接口. class CPU { public void startup(){ System.out.println("cpu start"); } public void shutdown(){ System.out.println("cpu stop"); } } class Memory { pu

Java设计模式(六)合成模式 享元模式

(十一)合成模式 Composite 合成模式是一组对象的组合,这些对象可以是容器对象,也可以是单对象.组对象允许包含单对象,也可以包含其他组对象,要为组合对象和单对象定义共同的行为.合成模式的意义是 保证客户端调用单对象与组合对象的一致性. class TreeNode{ private String name; private TreeNode parent; private Vector<TreeNode> children = new Vector<TreeNode>();

Java设计模式(一)普通工场模式,抽象工场模式

设计模式 设计模式我觉得是前人总结的,为了解决一类问题而总结的代码设计经验.最初可能为了使用而使用,后面就会发现,很多没想到的问题因为使用了正确的设计模式已经为你考虑到了.<design patterns设计模式>这本书是程序员进阶必学. (一)工厂模式 工厂模式的意义在于定义一个用于创建对象的接口,并控制返回哪个类的实例.网上比较流行的一个普通工厂模式的例子. interface Sender{ public void send(); } class MainSender implement

《JAVA与模式》之备忘录模式

备忘录模式又叫做快照模式(Snapshot Pattern)或Token模式,是对象的行为模式. 备忘录对象是一个用来存储另外一个对象内部状态的快照的对象.备忘录模式的用意是在不破坏封装的条件下,将一个对象的状态捕捉(Capture)住,并外部化,存储起来,从而可以在将来合适的时候把这个对象还原到存储起来的状态.备忘录模式常常与命令模式和迭代子模式一同使用. 备忘录模式的结构 备忘录模式的结构图如下所示 备忘录模式所涉及的角色有三个:备忘录(Memento)角色.发起人(Originator)角