首页 > 其他分享 >设计模式之(5)——原型模式

设计模式之(5)——原型模式

时间:2022-08-31 14:11:08浏览次数:52  
标签:设计模式 对象 clone 模式 Shape 原型 null type public

  上篇文章中我们提到单例模式可以避免重复创建消耗资源的对象,但是却不得不共用对象。若是对象本身也不让随意访问修改时,怎么办?那么我们就可以采用原型模式来创建新的实例。

  定义:原型模式用来创建重复对象,当直接创建对象的代价比较大的时候可以采用这种模式,这种模式实现了一个原型接口,这个接口用于创建当前对象的克隆,同时又能保证性能,属于一种创建型模式;

  意图:用原型对象指定要创建对象的类型,并通过拷贝原型对象来创建新的对象;

  主要解决:在直接创建对象代价比较大的时候采用这种模式;

  关键代码:1、实现克隆Cloneable接口,重写Object中的clone方法,通过实现对象的浅拷贝或者通过序列化和反序列化来实现对象的深拷贝;2、原型模式同样用于隔离对象的使用者和具体类型之间的耦合关系,它同样要求这些“易变类”拥有稳定的接口;

  应用实例:1、细胞分裂;

  优点:1、性能提高;2、逃避构造函数的约束;

  缺点:1、配备克隆方法需要对类的功能进行全面考虑,对于全新的类并不难,但是对于已有的类却不容易,例如引用中含有循环结构的时候;2、必须实现clone接口;

  使用场景:1、资源优化场景,类的初始化需要消耗非常多的资源的时候,包括数据和硬件资源;2、性能和安全要求的场景;3、通过new产生一个对象需要非常频繁地数据准备或者权限访问的时候;4、一个对象提供给其他对象访问,而各个调用者都可能需要对其进行修改的时候;5、通常和工厂方法一起出现,通过原型模式创建对象,然后由工厂方法提供给调用者;

  UML类图:

  以下是Demo源码:

package cn.com.pep.model.prototype;

/**
 * 
 * @Title: Shape
 * @Description:
 * @author wwh
 * @date 2022-8-25 16:48:21
 */
public abstract class Shape implements Cloneable {

	String id;

	String type;

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}

	/**
	 * @Title: draw
	 * @Description:
	 */
	public abstract void draw();

	@Override
	public Object clone() throws CloneNotSupportedException {
		try {
			return super.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return null;
	}

}

  

package cn.com.pep.model.prototype;

/**
 * 
 * @Title: Circle
 * @Description:
 * @author wwh
 * @date 2022-8-25 16:51:33
 */
public class Circle extends Shape {

    public Circle() {
        type = "circle";
    }

    @Override
    public void draw() {
        System.err.println("Draw a Circle!");
    }

}
package cn.com.pep.model.prototype;

/**
 * 
 * @Title: Rectangle
 * @Description:
 * @author wwh
 * @date 2022-8-25 16:55:02
 */
public class Rectangle extends Shape {

    public Rectangle() {
        type = "rectangle";
    }

    @Override
    public void draw() {
        System.err.println("Draw a rectangle!");
    }

}
package cn.com.pep.model.prototype;

/**
 * 
 * @Title: Square
 * @Description:
 * @author wwh
 * @date 2022-8-25 16:53:52
 */
public class Square extends Shape {

    public Square() {
        type = "square";
    }

    @Override
    public void draw() {
        System.err.println("Draw a Square!");
    }

}
package cn.com.pep.model.prototype;

import java.util.Hashtable;

/**
 * 
 * @Title: ShapeFactory
 * @Description:
 * @author wwh
 * @date 2022-8-25 16:56:33
 */
public class ShapeFactory {

    private static Hashtable<String, Shape> t = new Hashtable<>();
    
    /**
     * 类加载的时候通过静态块完成原型对象的初始化
     */
    static {
        Circle circle = new Circle();
        t.put("circle", circle);
        Square square = new Square();
        t.put("square", square);
        Rectangle rectangle = new Rectangle();
        t.put("rectangle", rectangle);
    }
    
    public static Shape getShape(String type) {
        Shape clone = null;
        try {
            Shape shape = t.get(type);
            clone = (Shape) shape.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return clone;
    }


}
package cn.com.pep.model.prototype;
/**
 * 
 * @Title: PrototypePatternDemo  
 * @Description:  
 * @author wwh 
 * @date 2022-8-25 17:02:02
 */
public class PrototypePatternDemo {
    
    public static void main(String[] args) {
        Shape circle = ShapeFactory.getShape("circle");
        System.err.println(circle);
        
        Shape square = ShapeFactory.getShape("square");
        System.err.println(square);
        
        Shape rectangle = ShapeFactory.getShape("rectangle");
        System.err.println(rectangle);
    }

}

  以上代码中采用了浅拷贝调用super.clone()方法来实现原型模式,被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用都仍然指向原来的对象,这就是浅拷贝,当然也可以采用序列化和反序列化来实现深拷贝通过原型对象生成目标对象,代码如下:

    public Object clone() throws CloneNotSupportedException {
//        try {
//            return super.clone();
//        } catch (CloneNotSupportedException e) {
//            e.printStackTrace();
//        }
//        return null;
        ByteArrayOutputStream bos = null;
        ObjectOutputStream oos = null;
        ByteArrayInputStream bis = null;
        ObjectInputStream ois = null;
        Object obj = null;
        try {
            /* 序列化 */
            bos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(bos);
            oos.writeObject(this);
            /* 反序列化 */
            bis = new ByteArrayInputStream(bos.toByteArray());
            ois = new ObjectInputStream(bis);
            obj = ois.readObject();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            try {
                if (bos != null) {
                    bos.close();
                }
                if (oos != null) {
                    oos.close();
                }

                if (bis != null) {
                    bis.close();
                }
                if (ois != null) {
                    ois.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }

        return obj;
    }

  深拷贝是通过流来生成对象的,生成的对象就和原型对象完全是两个对象啦。

标签:设计模式,对象,clone,模式,Shape,原型,null,type,public
From: https://www.cnblogs.com/wha6239/p/16642206.html

相关文章

  • C++ 简单设计模式之简单工厂
    一、简单工厂一个工厂类能够根据传入参数而决定创建出哪一种产品类的实例二、类设计//手机classPhone{public: virtualvoidmodel()=0;};//华为手机clas......
  • 【设计模式】25.行为型模式-解释器(Interpreter)
    一、描述给定一个语言,定义它的文法的一种标识,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。解释器模式为自定义语言的设计和实现提供了一种解决方案,它用......
  • 第 17 天:没有资产的原型制作的好处
    第17天:没有资产的原型制作的好处客观的:为什么需要在制作前制作游戏原型?所以现在我刚刚结束了我项目的原型阶段,让我们来谈谈为什么在游戏开发中进行原型设计是必要......
  • 2022 年 8 月前端更新:TypeScript、软件设计模式、焦点样式和单个 CSS 转换属性中的 SO
    2022年8月前端更新:TypeScript、软件设计模式、焦点样式和单个CSS转换属性中的SOLID原则本月我们将介绍TypeScript中的SOLID原则、React应用程序的软件设计模......
  • 模板、策略以及工厂模式
    记录学习过程中的问题,实操总结,方便回顾。模板方法属于行为设计模式;在父类中定义一个算法的框架,允许子类在不修改结果的情况下重写算法的特定步骤。应用场景:当多个产......
  • 静态——字段与属性、方法与类、单例设计模式
    1、static关键字static关键字,用于修饰类,字段,属性,方法,构造方法等。被static修饰的类称之为“静态类”;被static修饰的成员称之为“静态成员”;被修饰过的成员分别称为:......
  • 单例模式
    单例模式是什么?为什么要使用单例模式单例模式,顾名思义就是在整个运行时域,一个类只有一个实例对象为什么要用单例呢。因为有的类的,比较庞大和复杂,如果频繁创建和销毁对象,......
  • C# 装饰模式
    //Seehttps://aka.ms/new-console-templateformoreinformation/**个人理解你要往原有的东西上加东西Phone=装饰手机原材料Decorator=装饰手机中间人Xiao......
  • C嵌入式编程设计模式-C语言类实现方式
    类的封装方式以文件作为封装边界,将外部调用的函数声明,全局变量变量放入头文件中,将具体实现放入.c文件中。简单栈的实现代码:/************************************......
  • js 严格模式
    //js使用严格模式可以规范我们写代码//要启用严格模式,您只需要在JavaScript脚本的开头添加"usestrict";或'usestrict';指令即可,如下所示:<script>"usestrict";......