装饰器设计模式

通俗的讲装饰器就是在不改变对象结构的前提下,扩充对象的功能。

下面以effective java中例题

问题  我想扩充Hash<set>功能,使得能够统计添加过元素的个数?

或许你可能会自定义一个类通过继承扩展,从而实现计数功能,代码如下:

package com.effectJava.Chapter2;

import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;

public class InstrumentedHashSet<E> extends HashSet<E> {
    private int addCount=0;

    public InstrumentedHashSet() {
    }
    public InstrumentedHashSet(int initCap,float loadFactor) {
        super(initCap, loadFactor);
    }
@Override
    public boolean add(E e) {
        addCount++;
        return super.add(e);
    }

    @Override
    public boolean addAll(Collection<? extends E> c) {
        addCount += c.size();//删除
        return super.addAll(c);
    }

    public int getAddCount() {
        return addCount;
    }

    public static void main(String... args) {
        InstrumentedHashSet s = new InstrumentedHashSet<String>();
        s.addAll(Arrays.asList("shape", "Crackle", "Pop"));
        System.out.println(s.getAddCount());
    }
}

  上面代码直接继承hashSet类,然后覆盖 add和addAll方法 ,你会发现最终结果不是3,而是6,其实addAll内部实现是通过调用add,可能你又想到可以通过删除addAll方法上的 标志删除的那行代码,通过上述操作确实能够实现功能,但是这种功能的实现的子类比较脆弱,如果父类增加新方法,或者原方法有改动,都可能导致统计失败。

为此我们提出装饰器设计模式,  通过被装饰者和装饰者之间的互相调用来实现扩展技术功能的目的。

首先定义一个装饰器基类ForwardingSet<E> 实现Set<E>接口,由于add和addAll方法都在Set接口中定义,因此可以通过实现此接口定义装饰器

package com.effectJava.Chapter2;

import java.util.Collection;
import java.util.Iterator;
import java.util.Set;

//装饰器
public class ForwardingSet<E> implements Set<E> {

    private final Set<E> set;
    public ForwardingSet(Set<E> set) {
        this.set = set;
    }

    @Override
    public int size() {
        return set.size();
    }

    @Override
    public boolean isEmpty() {
        return set.isEmpty();
    }

    @Override
    public boolean contains(Object o) {
        return set.contains(o);
    }

    @Override
    public Iterator<E> iterator() {
        return set.iterator();
    }

    @Override
    public Object[] toArray() {
        return set.toArray();
    }

    @Override
    public <T> T[] toArray(T[] a) {
        return set.toArray(a);
    }

    @Override
    public boolean add(E e) {
        return set.add(e);
    }

    @Override
    public boolean remove(Object o) {
        return set.remove(o);
    }

    @Override
    public boolean containsAll(Collection<?> c) {
        return set.containsAll(c);
    }

    @Override
    public boolean addAll(Collection<? extends E> c) {
        return set.addAll(c);
    }

    @Override
    public boolean retainAll(Collection<?> c) {
        return set.retainAll(c);
    }

    @Override
    public boolean removeAll(Collection<?> c) {
        return set.removeAll(c);
    }

    @Override
    public void clear() {
        set.clear();
    }
}

  定义一个装饰器类

package com.effectJava.Chapter2;

import java.util.*;

//具体的装饰器类
//装饰对象可以在转发这些请求以前或以后增加一些附加功能,这样就可以确保了在运行时,不用修改给定对象的结构就可以在外部增加附加的功能。
//在面向对象的设计中,通常通过继承来事项对给定类的功能扩展。
public class InstrumentedSet<E> extends ForwardingSet<E> {

    private  int CountSize=0;
    public InstrumentedSet(Set<E> set) {
        super(set);
    }
    @Override
    public boolean addAll(Collection<? extends E> c) {
        CountSize += c.size();
        return super.addAll(c);
    }

    @Override
    public boolean add(E e) {
        CountSize++;
        return super.add(e);
    }

    public int getCountSize() {
        return CountSize;
    }

  }

  定义一个被装饰者(这里我们直接用HashSet因为它实现类Set<E>,避免我们自己取实现)

 public static void main(String... args) {
//        HashSet是被装饰者, InstrumentedSet是装饰者
        InstrumentedSet<String> s = new InstrumentedSet<String>(new HashSet<String>());
        s.addAll(Arrays.asList("1", "2", "3"));
        System.out.println(s.getCountSize());//结果为3
    }

  总结   其实装饰器基类中有一个变量保存被装饰器类对象,装饰器和被装饰器的功能扩展是基于两者都实现相同的接口,即类型相同,然后可以互相发送消息,扩展功能。

原文地址:https://www.cnblogs.com/09120912zhang/p/8290281.html

时间: 2024-10-07 19:31:08

装饰器设计模式的相关文章

【ThinkingInJava】42、装饰器设计模式

/** * 书本:<Thinking In Java> * 功能:装饰器设计模式 * 装饰器模式使用分层对象来动态透明的向单个对象添加责任.装饰器指定包装在最初的对象周围的所有对象都具有相同的基本接口 * 某些事物是可装饰的,可以通过将其他类包装在这个可装饰对象的四周,来将功能分层. * 装饰器是通过使用组合和形式化结构(可装饰物/装饰器层次结构)来实现的,而混型是基于继承的 * 文件:Decoration.java * 时间:2015年4月21日10:18:43 * 作者:cutter_po

装饰器设计模式初探(Java实现)

本篇随笔主要介绍用Java实现简单的装饰器设计模式: 先来看一下装饰器设计模式的类图:  从图中可以看到,我们可以装饰Component接口的任何实现类,而这些实现类也包括了装饰器本身,装饰器本身也可以再被装饰. 下面是用Java实现的简单的装饰器设计模式,提供的是从基本的加入咖啡入手,可以继续加入牛奶,巧克力,糖的装饰器系统. 1 interface Component { 2 void method(); 3 } 4 class Coffee implements Component { 5

设计模式之---装饰器设计模式

职责:动态的为一个对象增加新的功能 装饰器模式是一种用于代替继承的技术,无需通过继承增加子类就能扩展对象的新功能.使用对象的关联关系代替继承关系,更加灵活,同时避免类型体系的快速膨胀. 实现细节: ——Component抽象构件角色:真实对象和装饰对象有相同的接口.这样,客户端对象就能够以与真实对象相同的方式同装饰对象交互. ——ConcreteComponent具体构件角色(真实对象):io流中的FileInputStream. FileOutputStream ——Decorator装饰角色

java 实现装饰器设计模式

package com.gylhaut.base; /** * 装饰器 * 类与类之间的关系 * 1.依赖:形参(局部变量) * 2.关联:属性 * 聚合 属性 整体和部分 不一致的生命周期 人和手 * 组合 属性 整体和部分 一致的生命周期 人和大脑 * 3.继承:父子类关系 * 4.实现:接口与实现的关系 */ public class Decorator { private Voice voice; public void say(){ System.out.println("val=&q

IOS设计模式之二(门面模式,装饰器模式)

本文原文请见:http://www.raywenderlich.com/46988/ios-design-patterns. 由 @krq_tiger(http://weibo.com/xmuzyq)翻译,如果你发现有什么错误,请与我联系谢谢. 门面(Facade)模式(译者注:facade有些书籍译为门面,有些书籍译为外观,此处译为门面) 门面模式针对复杂的子系统提供了单一的接口,不需要暴漏一些列的类和API给用户,你仅仅暴漏一个简单统一的API. 下面的图解释了这个概念: 这个API的使用者

设计模式之: 装饰器模式

什么是装饰器模式 作为一种结构型模式, 装饰器(Decorator)模式就是对一个已有结构增加"装饰". 适配器模式, 是为现在有结构增加的是一个适配器类,.将一个类的接口,转换成客户期望的另外一个接口.适配器让原本接口不兼容的类可以很好的合作. 装饰器模式是将一个对象包装起来以增强新的行为和责任.装饰器也称为包装器(类似于适配器) 有些设计设计模式包含一个抽象类,而且该抽象类还继承了另一个抽象类,这种设计模式为数不多,而装饰器就是其中之一. 什么时候使用装饰器模式 基本说来, 如果想

设计模式(八)装饰器模式Decorator(结构型)

设计模式(八)装饰器模式Decorator(结构型) 1. 概述 若你从事过面向对象开发,实现给一个类或对象增加行为,使用继承机制,这是所有面向对象语言的一个基本特性.如果已经存在的一个类缺少某些方法,或者须要给方法添加更多的功能(魅力),你也许会仅仅继承这个类来产生一个新类—这建立在额外的代码上. 通过继承一个现有类可以使得子类在拥有自身方法的同时还拥有父类的方法.但是这种方法是静态的,用户不能控制增加行为的方式和时机.如果  你希望改变一个已经初始化的对象的行为,你怎么办?或者,你希望继承许

[译]Python之装饰器知必会

装饰器基础 Python的函数是对象 为了理解装饰器, 你必须先理解: 在Python的世界, 函数是对象. 这一点很重要. 让我们通过一个简单的例子来看看为什么: def shout(word="yes"): return word.capitalize()+"!" print shout() # 输出 : 'Yes!' # 作为一个对象, 你可以像任何其他对象一样, 将函数赋值给一个变量 scream = shout # 注意, 我们并没有使用括号: # 我们没

Python 函数装饰器入门

原文链接: --> A guide to Python's function decorators Python功能强劲,语法表现力强,尤其装饰器深深的吸引着我.在设计模式中,装饰器可以在不使用子类的情况下,动态的改变函数,方法以及类的功能.这个功能非常有用,特别在你想扩展函数的功能同时又不想改变原有的函数.的确,我们任意的实现装饰器设计模式,但是,python通过提供简单的语法和特性让装饰器的实现变的如此简单. 在本文中,我将用一组例子来深入浅入python 函数装饰器的功能,所有的例子都是在