HeadFirst设计模式二十三【原型模式】

当创建给定类的实例的过程很昂贵或很复杂时,可以使用原型模式。原型模式的核心是复制,Java原生就是支持。因为所有的JavaBean都继承自Object,而Object类提供一个clone()方法,可以讲一个JavaBean对象复制一份。但是,这个JavaBean必须实现一个Cloneable接口,表明这个JavaBean支持复制。

场景描述

有一个场景可以很好地来理解这个模式,就是西游记里的孙悟空,拔毛一吹瞬间变出数百个一模一样的分身。或者火影忍者中鸣人地影分身也有异曲同工之妙。下面用孙悟空地例子来看下如何实现原型模式。

代码示例

  1. 创建金箍棒

    public class GoldRingedStaffimplements Cloneable,Serializable{
        // 金箍棒高度
        private float height = 100.0F;
        // 金箍棒直径
        private float diameter = 10.0F;
    
        /**
         * 增长行为,每次调用长度和半径增加一倍
         */
        public void grow(){
            this.diameter *= 2.0;
            this.height *= 2;
        }
    
        /**
         * 缩小行为,每次调用长度和半径减少一半
         */
        public void shrink(){
            this.diameter /= 2;
            this.height /= 2;
        }
    }
    
  2. 创建Monkey类,也就是大圣本尊,因为它是一只猴子

    public class Monkeyimplements Cloneable,Serializable{
        private int height;
        private int weight;
        private GoldRingedStaff staff;
        private Date birthDate;
    
        public GoldRingedStaff getStaff(){
            return staff;
        }
    
        public Date getBirthDate(){
            return birthDate;
        }
    
        public Monkey(){
            this.staff = new GoldRingedStaff();
            this.birthDate = new Date();
        }
    
        /**
         * 浅克隆
         */
        @Override
        public Object clone(){
            Monkey temp = null;
            try {
                temp = (Monkey) super.clone();
            } catch (CloneNotSupportedException e) {
                System.out.println("Clone failed");
            }
            return temp;
        }
    
        /**
         * 深克隆
         */
        public Object deepClone()throws IOException, ClassNotFoundException {
            // 将对象写出到流中
            ByteArrayOutputStream bo = new ByteArrayOutputStream();
            ObjectOutputStream oo = new ObjectOutputStream(bo);
            oo.writeObject(this);
    
            // 然后将对象从流中读出来
            ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
            ObjectInputStream oi = new ObjectInputStream(bi);
            return oi.readObject();
        }
    }
    
  3. 测试

    public class Test{
        public static void main(String[] args)throws IOException, ClassNotFoundException {
            Monkey monkey = new Monkey();
    
            // 浅克隆大圣
            Monkey copyMonkey = (Monkey) monkey.clone();
            System.out.println("Monkey King's birth date = " + monkey.getBirthDate());
            System.out.println("Copy Monkey's birth date = " + copyMonkey.getBirthDate());
            System.out.println("Monkey King == Copy Monkey ? " + (monkey == copyMonkey));
            // 浅克隆的话,金箍棒指向的对象是同一个
            System.out.println("Monkey King's Staff == Copy Monkey's Staff ? " + (monkey.getStaff() == copyMonkey.getStaff()));
    
            System.out.println();
    
            // 深克隆大圣
            Monkey deepCopyMonkey = (Monkey) monkey.deepClone();
            System.out.println("Monkey King's birth date = " + monkey.getBirthDate());
            System.out.println("Copy Monkey's birth date = " + deepCopyMonkey.getBirthDate());
            System.out.println("Monkey King == Copy Monkey ? " + (monkey == deepCopyMonkey));
            // 深克隆,所有对象都不是同一个
            System.out.println("Monkey King's Staff == Copy Monkey's Staff ? " + (monkey.getStaff() == deepCopyMonkey.getStaff()));
        }
    }
    

这个模式其实就是用了Java原生的功能,需要注意的是,使用浅克隆还是深克隆对程序影响很大,需要我们在使用过程中去考虑。本章节就到这里了。

我来评几句
登录后评论

已发表评论数()

相关站点

+订阅
热门文章