当前位置:编程学习 > JAVA >>

设计模式之不变设计模式

不变设计模式(immutable pattern)
1 定义
这些对象共享相同对象的引用,为此,在对象构造好之后,不允许改变共享对象的内容
 
2 例子
在jdk中String被设计为不可变类,一旦生成一个String对象,它的所有属性就不会被变,任何方法要么返回这个对象本身的原
始状态,要么抛弃原来的字符串返回一个新字符串,而绝对不会返回被修改了的字符串对象.
StringBuffer是可变类
3 如何设计不可变类
不变类,即类中的方法和属性不能被外界修改,包括其子类
1.类本身声明为final,可以保证它本身的状态不会被子类扩展方法所改变,即没有子类。
2.类的所有成员变量都是final的,保证它在构造后不会被重新赋值.而且类所有属性是private的,只提供getter访问.
3.类的能传入的参数是Immutable的,且返回的属性也是不可变的.
如果方法返回的属性是基本类型,则在类中将该属性声明为final即可。
如果是引用类型,该属性的final只能保证引用类型的引用地址不可变,无法保证外界对该引用类型内容的修改,所以一般返回该引用类型的一份拷贝。
注意:在将可变类封装到不变类的时候要特别小心.因为你传入的引用在外面是可以被修改的.所以即使你不变类本身不能去改变属性,但属性有一个外部引用.可以在外面修改。
4 优缺点
1)不变类优点:
多个线程共享一个不变类的实例时,这个实例的状态不会发生改变.事实上它没有地方让你去改变.所以多线程共享一个不变类的实例时,不需要进行临界区保护(即同步)。
2)不变类缺点:不灵活
 
5 应用
5.1设计一个缓存
例子:设计一个单例,属性HashMap已被赋值,外部只能使用属性HashMap的值,不能对其进行修改,所以只返回HashMap中的值,不返回该HashMap的引用地址。
 
[java]  
<span style="font-size:18px">/**  
 * Fuction: 
 * 输入参数是不可变的,返回的HashMap不是hm,即其引用地址,每次返回它的副本,所以外界也无法修改hm 
 * @author    E-mail:yangzhonglive@gmail.com 
 * @version  2013-10-7 下午9:57:16  
 * @since    1.0  
 */  
  
public final class ImmutableBuffer {  
  
    private volatile static ImmutableBuffer uniqueInstance=null;  
    private final HashMap hm=new HashMap();  
  
  
    private ImmutableBuffer(){    
        //设置缓存值  
        hm.put("a", 1);  
        hm.put("b", 2);  
    }  
  
    public static ImmutableBuffer getInstance(){  
       if(uniqueInstance==null){  
           synchronized (ImmutableBuffer.class){ //note we only synchronize the first time through!  
               if(uniqueInstance == null)   //once in the block,check again and if still null, create an instance  
                  uniqueInstance=new ImmutableBuffer();  
           }//end synchronized    
       }//end if  
          
       return uniqueInstance;  
    }//end geInstance()  
  
    public HashMap getHashMap(){  
       HashMap copy=new HashMap();  
       copy.putAll(hm);  
       return copy;  
    }//end getHashMap()  
      
    /** 
     * @param args 
     */  
    public static void main(String[] args) {  
        ImmutableBuffer ib=ImmutableBuffer.getInstance();  
        //尝试改变缓存值  
        HashMap hm=ib.getHashMap();  
        hm.put("c", 3);  
        //测试是否改变  
        HashMap hm2=ib.getHashMap();  
        Set entry=hm2.entrySet();  
        Iterator it=entry.iterator();  
        while(it.hasNext()){  
            Map.Entry me=(Map.Entry)it.next();  
            //获得关键字getKey(),获得值getValue()    
            System.out.println(me.getKey()+":"+me.getValue());   
        }//end while  
  
    }//end main()  
}</span>  
 
5.2 实现Immutable的FIFO队列,要求时间复杂度为O(1)
The Queue class represents an immutable first-in-first-out (FIFO) queue of  objects. Use two @see PersistentStack to implement the persistent queue.
 Every element is pushed on the incoming stack once, popped off the incoming  stack once, pushed on the outgoing stack once and popped off the outgoing stack once. enqueue(E) is O(1). Dequeuing is on average O(1), though it is  * O(n) for a single case which only few happens when reverse incoming stack elements into outgoing stack.
 
不变队列实现用2个不变栈来实现,不变栈类如下
 
[java]  
<span style="font-size:18px">/** 
 * Implement an persistent stack, here persistent stacks with the same tail can 
 * share state, saving on memory. 
 *  
 * @author  E-mail:yangzhonglive@gmail.com 
 * @version 2013-10-12 
 * @since 1.0 
 */  
public final class PersistentStack<E> implements Iterable<E> {  
  
    // ----------------------------------------------------  
    // ---private properties  
    // ----------------------------------------------------  
  
    /** 
     * The head value of this persistent stack. 
     */  
    private final E head;  
    /** 
     * The head of this persistent stack, and it is the tail reference of the 
     * stack which add element into this persistent stack 
     */  
    private final PersistentStack<E> tail;  
    /** 
     * The number of elements in this persistent stack. 
     */  
    private final int size;  
  
    // ----------------------------------------------------  
    // ---constructor  
    // ----------------------------------------------------  
  
    /** 
 
补充:软件开发 , Java ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,