论坛首页 Java企业应用论坛

Decorator 装饰器 模式 java基础类库上的列子

浏览 2726 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2010-01-09   最后修改:2010-01-22

这个列子是关于汉堡包要和什么材料搭配  汉堡包核心是面包 但中间夹得材料可以是各种食物 即装饰面包以不同的材料

 

 

 

 

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

   发表时间:2010-03-22  
楼主如果说Wrapper,更好地理解。
0 请登录后投票
   发表时间:2010-03-23  
一码子事,长沙程序员3年经验工资几何?房价几何
0 请登录后投票
   发表时间:2010-03-23  
lich0079 写道
一码子事,长沙程序员3年经验工资几何?房价几何



一般来说,工资买不起房~
0 请登录后投票
   发表时间:2010-03-23  
我要知道数据 不要结论
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics