zoukankan      html  css  js  c++  java
  • 从原型模式(Prototype Pattern)到 Clone

    前面提到抽象工厂的实现,这里说说抽象工厂的原型实现,与工厂方法的实现不同,原型实现有他自己的优点和缺点

    原型的优点:

    1. 效率:clone是native方法,比new的效率高,当使用复杂循环嵌套对象是尤为明显

    2. 不需要为每一个新增的product创造一个具体factory

    缺点:

    1. 如果需要深复制,则需要手写所有包含循环引用对象的类的clone方法,因为需要手动在clone方法里对引用对象进行clone,否则是浅复制

    2. 当需要改变一个克隆实例内部的值时,由于clone方法是无参方法,只能在clone完以后手动调用改变值得方法,且如果这个值是一个类的引用,则克隆应该建立在深复制的前提下,否则会污染原型数据

    3. 原型工厂有可能被初始化成不兼容组件的组合,例如 CatHead和DogBody的组合,实际上这也是原型的一个灵活性的体现之一

    4. 就Java而言,它的clone方法是protected方法,我们需要手动实现Clonable接口以后重写clone()方法将其改为public方法才能调用

    下面是一个例子

    工厂类,不在需要具体的工厂子类,而是通过构造方法设置原型来产生不同的工厂

    package factory;
    
    import product.Body;
    import product.Eye;
    import product.Head;
    
    /**
     * Created with IntelliJ IDEA.
     * User: zhenwei.liu
     * Date: 13-8-1
     * Time: 上午12:33
     * To change this template use File | Settings | File Templates.
     */
    public class ModuleFactory {
        private static ModuleFactory factory = new ModuleFactory();
        private static Head _head;   // 原型组件
        private static Body _body;
        private static Object lockObj = new Object();
    
        // 设置原型
        public static ModuleFactory createFactory(Head newHead, Body newBody) {
            if (newHead == null || newBody == null)
                throw new RuntimeException("Param newHead and newBody cannot be null");
    
            // 为简单起见,不考虑多线程问题,不使用延迟加载
            _head = newHead;
            _body = newBody;
    
            return factory;
        }
    
        public Head createHead() throws CloneNotSupportedException {
            Head head = (Head) _head.clone();
            return head;
        }
    
        // 重载方法
        public Head createHead(Eye eye) throws CloneNotSupportedException {
            Head head = (Head) _head.clone();
            // 必须在clone之后手动调用修改成员的方法
            head.setEye(eye);
            return head;
        }
    
        public Body createBody() throws CloneNotSupportedException {
            return (Body) _body.clone();
        }
    }

    产品类

    package product;
    
    /**
     * Created with IntelliJ IDEA.
     * User: zhenwei.liu
     * Date: 13-8-1
     * Time: 上午12:24
     * To change this template use File | Settings | File Templates.
     */
    public abstract class Head implements Cloneable {
        private Eye eye = new Eye("defaultEye");
    
        public Eye getEye() {
            return eye;
        }
    
        public void setEye(Eye eye) {
            this.eye = eye;
        }
    
        @Override
        public Object clone() throws CloneNotSupportedException {
            Head head = (Head) super.clone();
            // 对内部对象进行深复制
            head.setEye((Eye) eye.clone());
            return head;
        }
    
        public abstract void eat();
    }
    
    
    package product;
    
    /**
     * Created with IntelliJ IDEA.
     * User: zhenwei.liu
     * Date: 13-8-1
     * Time: 上午12:29
     * To change this template use File | Settings | File Templates.
     */
    public class DogHead extends Head {
        @Override
        public void eat() {
            System.out.println("A dooog's head is eating with its eye " + getEye().getName());
        }
    }
    
    package product;
    
    /**
     * Created with IntelliJ IDEA.
     * User: zhenwei.liu
     * Date: 13-8-1
     * Time: 上午12:29
     * To change this template use File | Settings | File Templates.
     */
    public class CatHead extends Head {
        @Override
        public void eat() {
            System.out.println("A caaat's head is eating fast");
        }
    }
    
    package product;
    
    /**
     * Created with IntelliJ IDEA.
     * User: zhenwei.liu
     * Date: 13-8-1
     * Time: 上午12:48
     * To change this template use File | Settings | File Templates.
     */
    public class Eye implements Cloneable{
        private String name;
    
        @Override
        public Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    
        public Eye(String name) {
            this.name = name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    }
    
    package product;
    
    /**
     * Created with IntelliJ IDEA.
     * User: zhenwei.liu
     * Date: 13-8-1
     * Time: 上午12:24
     * To change this template use File | Settings | File Templates.
     */
    public abstract class Body implements Cloneable {
        public abstract void dance();
    
        // 此处必须将clone方法重新声明为public方法
        @Override
        public Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    }
    
    
    package product;
    
    /**
     * Created with IntelliJ IDEA.
     * User: zhenwei.liu
     * Date: 13-8-1
     * Time: 上午12:27
     * To change this template use File | Settings | File Templates.
     */
    public class CatBody extends Body {
        @Override
        public void dance() {
            System.out.println("A caaat's body is dancing crazily!!");
        }
    }
    
    package product;
    
    /**
     * Created with IntelliJ IDEA.
     * User: zhenwei.liu
     * Date: 13-8-1
     * Time: 上午12:27
     * To change this template use File | Settings | File Templates.
     */
    public class DogBody extends Body {
        @Override
        public void dance() {
            System.out.println("A dooog's body is dancing!");
        }
    }

    测试类

    import factory.ModuleFactory;
    import product.*;
    
    /**
     * Created with IntelliJ IDEA.
     * User: zhenwei.liu
     * Date: 13-8-1
     * Time: 上午12:35
     * To change this template use File | Settings | File Templates.
     */
    public class Test {
    
        // 通过原型工厂克隆得到新的实例
        // 与具体实现无关的解耦代码
        private static void act(ModuleFactory factory) throws CloneNotSupportedException {
            Head head = factory.createHead();
            Body body = factory.createBody();
            head.eat();
            body.dance();
        }
    
        public static void main(String[] args) throws CloneNotSupportedException {
            Head head = new DogHead();
            head.getEye().setName("customEye");
            ModuleFactory factory = ModuleFactory.createFactory(head, new DogBody());
            factory.createHead().eat();
    
            // 测试深浅复制
            Head head2 = (Head) head.clone();
            head2.getEye().setName("smallEye");
            head2.eat();
            head.eat(); // 这里的输出发现eye并没有变成smallEye,所以可以确定eye是深复制
    
            System.out.println();
            factory = ModuleFactory.createFactory(new CatHead(), new CatBody());
            act(factory);
        }
    }

     输出

    A dooog's head is eating with its eye customEye
    A dooog's head is eating with its eye smallEye
    A dooog's head is eating with its eye customEye
    
    A caaat's head is eating fast
    A caaat's body is dancing crazily!!
  • 相关阅读:
    MYSQL连接不上100061错误
    最小生成树
    装载问题
    贪心算法-- 纪念品分组
    折腾日记----「乱七八糟的过程」
    LeetCode ---- 474. 一和零「二维01背包」
    Erlang TCP 实例
    Erlang 入门 ---- 基础(一)
    SpringBoot ---- Spring Security
    LeetCode----1026. 节点与其祖先之间的最大差值
  • 原文地址:https://www.cnblogs.com/zemliu/p/3229156.html
Copyright © 2011-2022 走看看