Java 5.原型模式学习

原型模式

可以复制已有对象,从而创建一个和原型对象相同的新对象。使用这种方式创建对象无需知道对象创建的细节,所以创建效率高效。

实现原型结构条件:

  1. 实现Cloneable接口;
  2. 重写clone方法;

1.模式结构图

在这里插入图片描述

2.模式的结构

  • 抽象原型类:规定了具体原型对象必须实现的接口。

  • 具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象。

  • 访问类:使用具体原型类中的 clone() 方法来复制新的对象。

3.模式的实现

3.1实现一

原型模式的克隆分为浅克隆和深克隆,Java中Object类提供的clone()方法属于浅克隆,Cloneable接口就是抽象原型;

具体原型类:

/**
 * 具体原型类:视频
 * 如何实现克隆:
 *  1.实现cloneable接口
 *  2.重写clone方法
 */
public class Video implements Cloneable{
    
    
    private String name;
    private Date date;

    public Video(String name, Date date) {
    
    
        this.name = name;
        this.date = date;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
    
    
        // 实现深克隆
        Video video = (Video) super.clone();

        //将对象属性也进行克隆
        video.date = (Date) this.getDate().clone();
        return video;
    }

   //getter/setter此处省略...

    @Override
    public String toString() {
    
    
        return "Video{" +
                "name='" + name + '\'' +
                ", date=" + date +
                '}';
    }
}

访问类:

/**
 * 访问类:客户端
 * 原型模式:
 * spring 中的bean 的创建有两种 :一种是单例模式 ,二是原型模式
 */
public class Bilibili {
    
    
    public static void main(String[] args) throws CloneNotSupportedException {
    
    
        clone1();
        System.out.println("\n");
        clone2();
    }

    /**
     * 克隆对象
     *
     * @throws CloneNotSupportedException
     */
    public static void clone1() throws CloneNotSupportedException {
    
    
        //原型对象 video1
        Video video = new Video("UP主A-视频一", DateUtil.date());
        System.out.println("video1 -> " + video);
        System.out.println("video1 hash-> " + video.hashCode());

        // UP主B 克隆 UP主A的视频
        Video video2 = (Video) video.clone();
        video2.setName("UP主B-视频一");
        System.out.println("video2 -> " + video2);
        System.out.println("video2 hash-> " + video2.hashCode());

        System.out.println("UP主A-视频一 == UP主B-视频一:" + (video == video2));
    }

    /**
     * 验证是否是浅克隆
     *
     * @throws CloneNotSupportedException
     */
    public static void clone2() throws CloneNotSupportedException {
    
    
        //克隆对象video3
        Date date = new Date();
        Video video = new Video("UP主A-视频一", date);
        Video video2 = (Video) video.clone();

        System.out.println("video1->" + video);
        System.out.println("video1 hash-> " + video.hashCode());
        System.out.println("video2->" + video2);
        System.out.println("video2 hash-> " + video2.hashCode());

        System.out.println("=================分割线==================");
        /*
            修改了date的值,video和video2 中的date都发生了变化
            说明video1和video2同时指向了date,video2只是把video的值和引用copy过来了,是浅克隆
         */
        date.setTime(1596596952);
        System.out.println("video1->" + video);
        System.out.println("video1 hash-> " + video.hashCode());
        System.out.println("video2->" + video2);
        System.out.println("video2 hash-> " + video2.hashCode());
    }
}

运行结果:

在这里插入图片描述

3.2实现二

原型模式可扩展为带原型管理器的原型模式,它在原型模式的基础上增加了一个原型管理器 PrototypeManager 类。该类用 HashMap 保存多个复制的原型,Client 类可以通过管理器的 get(String id) 方法从中获取复制的原型。

例:用带原型管理器的原型模式来生成包含“圆”和“三角形”等图形的原型,并计算其面积。分析:本实例中由于存在不同的图形类,例如,“圆”和“三角形”,它们计算面积的方法不一样,所以需要用一个原型管理器来管理它们,也可以通过原型管理器来添加新的图形原型;

  • 原型结构图
    在这里插入图片描述
  • 代码展示

抽象原型类

/**
 * 图形类
 */
public interface Shape extends Cloneable {
    
    
    Object clone();    //拷贝
    void countArea();    //计算面积
}

具体原型类

/**
 * 圆形类
 */
public class Circle implements Shape {
    
    
    //半径
    private int r;
    
    @Override
    public Object clone() {
    
    
        Circle circle = null;
        try {
    
    
            circle = (Circle) super.clone();
        } catch (CloneNotSupportedException e) {
    
    
            System.out.println("拷贝圆失败!");
        }
        return circle;
    }

    @Override
    public void countArea() {
    
    
        int r=0;
        System.out.print("这是一个圆,请输入圆的半径:");
        Scanner input=new Scanner(System.in);
        r=input.nextInt();
        System.out.println("该圆的面积="+Math.PI*r*r+"\n");
    }
}
/* *************分割线************* */
/**
 * 三角形
 */
public class Rectangle implements Shape {
    
    

    //宽
    public int width;
    //高
    public int height;

    @Override
    public Object clone() {
    
    
        Rectangle rectangle = null;
        try {
    
    
            rectangle = (Rectangle) super.clone();
        } catch (CloneNotSupportedException e) {
    
    
            System.out.println("拷贝正方形失败!");
        }
        return rectangle;
    }

    @Override
    public void countArea() {
    
    
        System.out.print("这是一个三角形,请输入它的底:");
        Scanner input = new Scanner(System.in);
        width = input.nextInt();
        System.out.print("这是一个三角形,请输入它的高:");
        height = input.nextInt();
        System.out.println("该三角形的面积=" + (width * height)/2 + "\n");
    }
}
/* *************分割线************* */
/**
 * 正方形
 */
public class Square implements Shape {
    
    

    //边长
    public int length;

    public Object clone() {
    
    
        Square square = null;
        try {
    
    
            square = (Square) super.clone();
        } catch (CloneNotSupportedException e) {
    
    
            System.out.println("拷贝正方形失败!");
        }
        return square;
    }

    public void countArea() {
    
    
        System.out.print("这是一个正方形,请输入它的边长:");
        Scanner input = new Scanner(System.in);
        length = input.nextInt();
        System.out.println("该正方形的面积=" + length * length + "\n");
    }
}

原型管理器类

/**
 * 原型管理器
 */
public class ProtoTypeManager {
    
    
    private Map<String, Shape> map = new HashMap<String, Shape>();

    public ProtoTypeManager() {
    
    
        map.put("Circle", new Circle());
        map.put("Rectangle", new Rectangle());
    }

    public void addShape(String key, Shape obj) {
    
    
        map.put(key, obj);
    }

    public Shape getShape(String key) {
    
    
        Shape temp = map.get(key);
        return (Shape) temp.clone();
    }
}

访问类

public class ProtoTypeShape {
    
    
    public static void main(String[] args) {
    
    
        ProtoTypeManager pm = new ProtoTypeManager();
        Shape circle = pm.getShape("Circle");
        circle.countArea();
        Shape rectangle = pm.getShape("Rectangle");
        rectangle.countArea();
        pm.addShape("Square",new Square());
        Shape square = pm.getShape("Square");
        square.countArea();
    }
}
 /*================= 输出结果================
 	这是一个圆,请输入圆的半径:3
    该圆的面积=28.274333882308138

    这是一个三角形,请输入它的底:3
    这是一个三角形,请输入它的高:2
    该三角形的面积=3

    这是一个正方形,请输入它的边长:3
    该正方形的面积=9
   ================= 输出结果================*/

猜你喜欢

转载自blog.csdn.net/zhuzicc/article/details/107865943