设计模式-PROTOTYPE(原型模式)

代码示例:https://github.com/elfc/patterns

分类

创建型

意图

用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

动机

考虑一个五金配件商(Hardware)可以生产螺丝(ScrewHardware)和螺母(NutHardware), 生产所采用的模型、样式、材料都一样只是大小不同,每生产一个螺丝或螺母创建一个对象,这些实例只是在初始化对象的时候大小有所不同,这样做会产生大量的重复操作,解决办法是可以生成一个管理类(PrototypeManager),让这个管理类来拷贝或者“克隆”一个Hardware, 我们称这个实例为一个原型

适用性

  • 当一个系统应该独立于它的产品创建、构成和表示时,要使用Prototype模式
  • 当要实例化的类是在运行时刻指定时,例如动态装载
  • 为了避免创建一个与产品类平行的工厂类层次时
  • 当一个类的实例只能有几种状态组合中的一种时。建立相应数据的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些

结构

参与者

  • Prototype(Hardware)
    -- 声明一个克隆自身的接口。
  • ConcretePrototype(ScrewHardware、NutHardware)
    -- 实现一个克隆自身的操作。
  • Client
    -- 让一个原型克隆自身从而创建一个新的对象

效果

  • 对客户隐藏了具体的产品类,因此减少了客户知道的名字的数目。
  • 客户无需改变即可使用与特定应用相关的类。
  • 运行时刻增加和删除产品。
  • 改变值以指定新对象

Tips

注意深拷贝与浅拷贝

代码示例


/**
 * @author chunyuliu
 */
@Data
public abstract class Hardware implements Cloneable {

    /** 大小 */
    int size;

    /** 模型 */
    String model;

    /** 样式 */
    String style;

    /** 材料 */
    String material;

    @Override
    public Hardware clone() {
        Hardware clone = null;
        try {
            clone = (Hardware) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return clone;
    }
}
/**
 * @author chunyuliu
 */
@Data
public class ScrewHardware extends Hardware {

    /** 大小 */
    int size;

    /** 模型 */
    String model;

    /** 样式 */
    String style;

    /** 材料 */
    String material;
}
/**
 * @author chunyuliu
 */
@Data
public class NutHardware extends Hardware {

    /** 大小 */
    int size;

    /** 模型 */
    String model;

    /** 样式 */
    String style;

    /** 材料 */
    String material;
}
/**
 * @author chunyuliu
 */
public class PrototypeManager {

    private static Hashtable hardwareMap
            = new Hashtable();

    public static Hardware getHardware(String hardwareId) {
        return  hardwareMap.get(hardwareId).clone();
    }

    /**
     * 加载不同类型的原型
     */
    public static void load() {
        Hardware screw = new ScrewHardware();
        screw.setModel("螺丝模型");
        screw.setStyle("花纹");
        screw.setMaterial("不锈钢");
        hardwareMap.put("screw", screw);

        Hardware nut = new NutHardware();
        nut.setModel("螺母模型");
        nut.setStyle("花纹");
        nut.setMaterial("不锈钢");
        hardwareMap.put("nut", nut);
    }
}
/**
 * @author chunyuliu
 */
public class PrototypeTest {

    @Test
    public void screwHardwareTest() {
        PrototypeManager.load();

        // 生产小号螺丝
        Hardware screwSmallSize = PrototypeManager.getHardware("screw");
        screwSmallSize.setSize(1);
        System.out.println(screwSmallSize);

        // 生产中号螺丝
        Hardware screwMiddleSmall = PrototypeManager.getHardware("screw");
        screwMiddleSmall.setSize(2);
        System.out.println(screwMiddleSmall);

        // 生产小号螺母
        Hardware nutSmallSize = PrototypeManager.getHardware("nut");
        nutSmallSize.setSize(1);
        System.out.println(nutSmallSize);
    }
}

你可能感兴趣的:(设计模式-PROTOTYPE(原型模式))