这个列子是关于汉堡包要和什么材料搭配 汉堡包核心是面包 但中间夹得材料可以是各种食物 即装饰面包以不同的材料
Ingredient 装饰器和被装饰着都要继承的类 也可定义为接口
package decoratorPatternSample;
public abstract class Ingredient {
public abstract String getDescription();
public abstract double getCost();
public void printDescription(){
System.out.println(" Name "+ this.getDescription());
System.out.println(" Price RMB "+ this.getCost());
}
}
Bread 核心组件
package decoratorPatternSample;
public class Bread extends Ingredient {
private String description;
public Bread(String desc) {
this.description = desc;
}
public String getDescription() {
return description;
}
public double getCost() {
return 2.48;
}
}
Decorator 装饰器类基类
package decoratorPatternSample;
public abstract class Decorator extends Ingredient {
Ingredient ingredient ;
public Decorator(Ingredient igd){
this.ingredient = igd;
}
public abstract String getDescription();
public abstract double getCost();
}
下面是4中装饰器实现类
package decoratorPatternSample;
public class Celery extends Decorator{
public Celery(Ingredient igd){
super(igd);
}
public String getDescription(){
String base = ingredient.getDescription();
return base +"\n"+"Decrocated with Celery !";
}
public double getCost(){
double basePrice = ingredient.getCost();
double celeryPrice =0.6;
return basePrice + celeryPrice ;
}
}
package decoratorPatternSample;
public class GreenGrocery extends Decorator{
public GreenGrocery (Ingredient igd){
super(igd);
}
public String getDescription(){
String base = ingredient.getDescription();
return base +"\n"+"Decrocated with GreenGrocery !";
}
public double getCost(){
double basePrice = ingredient.getCost();
double greenGroceryPrice = 0.4;
return basePrice + greenGroceryPrice ;
}
}
package decoratorPatternSample;
public class Mutton extends Decorator{
public Mutton(Ingredient igd){
super(igd);
}
public String getDescription(){
String base = ingredient.getDescription();
return base +"\n"+"Decrocated with Mutton !";
}
public double getCost(){
double basePrice = ingredient.getCost();
double muttonPrice = 2.3;
return basePrice + muttonPrice ;
}
}
package decoratorPatternSample;
public class Pork extends Decorator{
public Pork(Ingredient igd){
super(igd);
}
public String getDescription(){
String base = ingredient.getDescription();
return base +"\n"+"Decrocated with Pork !";
}
public double getCost(){
double basePrice = ingredient.getCost();
double porkPrice = 1.8;
return basePrice + porkPrice ;
}
}
测试类
package decoratorPatternSample;
public class DecoratorTest {
public static void main(String[] args) {
Ingredient compound = new Mutton(new Celery(new Bread("Master24's Bread")));
compound.printDescription();
compound = new Celery(new GreenGrocery(new Bread("Bread with milk")));
compound.printDescription();
compound = new Mutton(new Pork(new Bread("Bread with cheese")));
compound.printDescription();
}
}
输出
Name Master24's Bread
Decrocated with Celery !
Decrocated with Mutton !
Price RMB 5.38
Name Bread with milk
Decrocated with GreenGrocery !
Decrocated with Celery !
Price RMB 3.48
Name Bread with cheese
Decrocated with Pork !
Decrocated with Mutton !
Price RMB 6.58
===========================
java基础类库上的用法
Collections 类提供了一些集合类的帮助方法 ,如把集合转换成 checked unmodifiable Synchronized等
这些都是用的装饰器模式
这面给出一个把map转成同步map的列子
调用代码如下 相当于客户代码
public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {
return new SynchronizedMap<K,V>(m);
}
给一个map return一个 SynchronizedMap ,给原来的map添加了同步的功能(实际上这个新的map和原来的不是一个对象了,但客户是看不到这一点,但假如使用==的话 就会发现),保证线程的安全
接下来看下SynchronizedMap 是如何包装的
private static class SynchronizedMap<K,V>
implements Map<K,V>, Serializable {
// use serialVersionUID from JDK 1.2.2 for interoperability
private static final long serialVersionUID = 1978198479659022715L;
private Map<K,V> m; // Backing Map
Object mutex; // Object on which to synchronize
SynchronizedMap(Map<K,V> m) {
if (m==null)
throw new NullPointerException();
this.m = m;
mutex = this;
}
SynchronizedMap(Map<K,V> m, Object mutex) {
this.m = m;
this.mutex = mutex;
}
public int size() {
synchronized(mutex) {return m.size();}
}
public boolean isEmpty(){
synchronized(mutex) {return m.isEmpty();}
}
public boolean containsKey(Object key) {
synchronized(mutex) {return m.containsKey(key);}
}
public boolean containsValue(Object value){
synchronized(mutex) {return m.containsValue(value);}
}
public V get(Object key) {
synchronized(mutex) {return m.get(key);}
}
public V put(K key, V value) {
synchronized(mutex) {return m.put(key, value);}
}
public V remove(Object key) {
synchronized(mutex) {return m.remove(key);}
}
public void putAll(Map<? extends K, ? extends V> map) {
synchronized(mutex) {m.putAll(map);}
}
public void clear() {
synchronized(mutex) {m.clear();}
}
private transient Set<K> keySet = null;
private transient Set<Map.Entry<K,V>> entrySet = null;
private transient Collection<V> values = null;
public Set<K> keySet() {
synchronized(mutex) {
if (keySet==null)
keySet = new SynchronizedSet<K>(m.keySet(), mutex);
return keySet;
}
}
public Set<Map.Entry<K,V>> entrySet() {
synchronized(mutex) {
if (entrySet==null)
entrySet = new SynchronizedSet<Map.Entry<K,V>>((Set<Map.Entry<K,V>>)m.entrySet(), mutex);
return entrySet;
}
}
public Collection<V> values() {
synchronized(mutex) {
if (values==null)
values = new SynchronizedCollection<V>(m.values(), mutex);
return values;
}
}
public boolean equals(Object o) {
synchronized(mutex) {return m.equals(o);}
}
public int hashCode() {
synchronized(mutex) {return m.hashCode();}
}
public String toString() {
synchronized(mutex) {return m.toString();}
}
private void writeObject(ObjectOutputStream s) throws IOException {
synchronized(mutex) {s.defaultWriteObject();}
}
}
SynchronizedMap 实现了map接口,然后在内部把传进来的map用一个property保存住,然后在所有的map接口方法中都加上了锁
同理的看下 UnmodifiableMap
private static class UnmodifiableMap<K,V> implements Map<K,V>, Serializable {
// use serialVersionUID from JDK 1.2.2 for interoperability
private static final long serialVersionUID = -1034234728574286014L;
private final Map<? extends K, ? extends V> m;
UnmodifiableMap(Map<? extends K, ? extends V> m) {
if (m==null)
throw new NullPointerException();
this.m = m;
}
public int size() {return m.size();}
public boolean isEmpty() {return m.isEmpty();}
public boolean containsKey(Object key) {return m.containsKey(key);}
public boolean containsValue(Object val) {return m.containsValue(val);}
public V get(Object key) {return m.get(key);}
public V put(K key, V value) {
throw new UnsupportedOperationException();
}
public V remove(Object key) {
throw new UnsupportedOperationException();
}
public void putAll(Map<? extends K, ? extends V> t) {
throw new UnsupportedOperationException();
}
public void clear() {
throw new UnsupportedOperationException();
}
private transient Set<K> keySet = null;
private transient Set<Map.Entry<K,V>> entrySet = null;
private transient Collection<V> values = null;
public Set<K> keySet() {
if (keySet==null)
keySet = unmodifiableSet(m.keySet());
return keySet;
}
public Set<Map.Entry<K,V>> entrySet() {
if (entrySet==null)
entrySet = new UnmodifiableEntrySet<K,V>(m.entrySet());
return entrySet;
}
public Collection<V> values() {
if (values==null)
values = unmodifiableCollection(m.values());
return values;
}
public boolean equals(Object o) {return m.equals(o);}
public int hashCode() {return m.hashCode();}
public String toString() {return m.toString();}
/**
* We need this class in addition to UnmodifiableSet as
* Map.Entries themselves permit modification of the backing Map
* via their setValue operation. This class is subtle: there are
* many possible attacks that must be thwarted.
*
* @serial include
*/
static class UnmodifiableEntrySet<K,V>
extends UnmodifiableSet<Map.Entry<K,V>> {
private static final long serialVersionUID = 7854390611657943733L;
UnmodifiableEntrySet(Set<? extends Map.Entry<? extends K, ? extends V>> s) {
super((Set<Map.Entry<K,V>>)(Set)s);
}
public Iterator<Map.Entry<K,V>> iterator() {
return new Iterator<Map.Entry<K,V>>() {
Iterator<? extends Map.Entry<? extends K, ? extends V>> i = c.iterator();
public boolean hasNext() {
return i.hasNext();
}
public Map.Entry<K,V> next() {
return new UnmodifiableEntry<K,V>(i.next());
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
public Object[] toArray() {
Object[] a = c.toArray();
for (int i=0; i<a.length; i++)
a[i] = new UnmodifiableEntry<K,V>((Map.Entry<K,V>)a[i]);
return a;
}
public <T> T[] toArray(T[] a) {
// We don't pass a to c.toArray, to avoid window of
// vulnerability wherein an unscrupulous multithreaded client
// could get his hands on raw (unwrapped) Entries from c.
Object[] arr =
c.toArray(
a.length==0 ? a :
(T[])java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), 0));
for (int i=0; i<arr.length; i++)
arr[i] = new UnmodifiableEntry<K,V>((Map.Entry<K,V>)arr[i]);
if (arr.length > a.length)
return (T[])arr;
System.arraycopy(arr, 0, a, 0, arr.length);
if (a.length > arr.length)
a[arr.length] = null;
return a;
}
/**
* This method is overridden to protect the backing set against
* an object with a nefarious equals function that senses
* that the equality-candidate is Map.Entry and calls its
* setValue method.
*/
public boolean contains(Object o) {
if (!(o instanceof Map.Entry))
return false;
return c.contains(new UnmodifiableEntry<K,V>((Map.Entry<K,V>) o));
}
/**
* The next two methods are overridden to protect against
* an unscrupulous List whose contains(Object o) method senses
* when o is a Map.Entry, and calls o.setValue.
*/
public boolean containsAll(Collection<?> coll) {
Iterator<?> e = coll.iterator();
while (e.hasNext())
if (!contains(e.next())) // Invokes safe contains() above
return false;
return true;
}
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof Set))
return false;
Set s = (Set) o;
if (s.size() != c.size())
return false;
return containsAll(s); // Invokes safe containsAll() above
}
/**
* This "wrapper class" serves two purposes: it prevents
* the client from modifying the backing Map, by short-circuiting
* the setValue method, and it protects the backing Map against
* an ill-behaved Map.Entry that attempts to modify another
* Map Entry when asked to perform an equality check.
*/
private static class UnmodifiableEntry<K,V> implements Map.Entry<K,V> {
private Map.Entry<? extends K, ? extends V> e;
UnmodifiableEntry(Map.Entry<? extends K, ? extends V> e) {this.e = e;}
public K getKey() {return e.getKey();}
public V getValue() {return e.getValue();}
public V setValue(V value) {
throw new UnsupportedOperationException();
}
public int hashCode() {return e.hashCode();}
public boolean equals(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry t = (Map.Entry)o;
return eq(e.getKey(), t.getKey()) &&
eq(e.getValue(), t.getValue());
}
public String toString() {return e.toString();}
}
}
}
当尝试改变map的时候就会抛出UnsupportedOperationException