一周两个设计模式—设计模式之原型模式(第一周)

举报
浮生闲半日 发表于 2021/11/10 13:33:10 2021/11/10
【摘要】 书接前文,今天继续讲创建型模式中的原型模式。讲解设计模式肯定需要讲解其适用场景否则讲了一堆的定义,遇到场景还是想不起来,等大牛过来告诉你这般如此的实现或者看到别人的代码,才恍然大悟,原来这个模式我知道。话虽如此应该知道的定义还得啰嗦一下原型模式(Prototype Pattern):使用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。原型模式是一种对象创建型模式。需要注意的是通...

书接前文,今天继续讲创建型模式中的原型模式。
讲解设计模式肯定需要讲解其适用场景否则讲了一堆的定义,遇到场景还是想不起来,等大牛过来告诉你这般如此的实现或者看到别人的代码,才恍然大悟,原来这个模式我知道。

话虽如此应该知道的定义还得啰嗦一下

原型模式(Prototype Pattern):使用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
原型模式是一种对象创建型模式。

需要注意的是通过克隆方法所创建的对象是全新的对象,它们在内存中拥有新的地址,
通常对克隆所产生的对象进行修改对原型对象不会造成任何影响,
每一个克隆对象都是相互独立的。通过不同的方式修改可以得到一系列相似但不完全相同的对象。

在说一下原型模式的使用场景

对象之间相同或相似,即只是个别的几个属性不同的时候。
创建对象成本较大,例如初始化时间长,占用CPU太多,或者占用网络资源太多等,需要优化资源。
创建一个对象需要繁琐的数据准备或访问权限等,需要提高性能或者提高安全性。
系统中大量使用该类对象,且各个调用者都需要给它的属性重新赋值。

再来说一下原型模式优缺点

优点

Java 自带的原型模式基于内存二进制流的复制,在性能上比直接 new 一个对象更加优良。
可以使用深克隆方式保存对象的状态,使用原型模式将对象复制一份,并将其状态保存起来,简化了创建对象的过程,
以便在需要的时候使用(例如恢复到历史某一状态),可辅助实现撤销操作。

缺点

需要为每一个类都配置一个 clone 方法
clone 方法位于类的内部,当对已有类进行改造的时候,需要修改代码,违背了开闭原则。
当实现深克隆时,需要编写较为复杂的代码,而且当对象之间存在多重嵌套引用时,为了实现深克隆,
每一层对象对应的类都必须支持深克隆,实现起来会比较麻烦。因此,深克隆、浅克隆需要运用得当。

实现方式 只是java的实现方式,java提供了clone方法,只需要实现Cloneable接口即可,代码均使用kotlin

class Prototype(var name:String,var content:String,var school:String) : Cloneable {


    public override fun clone(): Prototype {
        var prototype: Prototype? = null
        prototype = super.clone() as Prototype
        return prototype
    }


    fun showMsg(){
        Log.v("======","祝贺$name $content$school")
    }
}

引用:

var  prototype = Prototype("张三","同学:在2016学年第一学期中表现优秀,被评为三好学生。","韶关学校")
var prototypeOther = prototype.clone()
prototypeOther.name = "Jim"
prototypeOther.school = "工业大学"

findViewById<Button>(R.id.btnFirst).setOnClickListener {
    prototype.showMsg()
}
findViewById<Button>(R.id.btnSecond).setOnClickListener {
    prototypeOther.showMsg()
}

这样一个简单的原型模式就完事了。

当然还可以扩展一下原型模式,例如之前的农场问题,不过这次咱们不下乡了,咱们直接走进课堂,求图形的面积,不同的图形面积的公式是不同的,这个时候就得想办法解决了。

抽象面积计算公式

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

具体实现

//圆形
class Circle implements Shape {
public Object clone() {
Circle w = null;
try {
w = (Circle) super.clone();
} catch (CloneNotSupportedException e) {
System.out.println("拷贝圆失败!");
}
return w;
}
public void countArea() {
int r = 0;
System.out.print("这是一个圆,请输入圆的半径:");
Scanner input = new Scanner(System.in);
r = input.nextInt();
System.out.println("该圆的面积=" + 3.1415 * r * r + "\n");
}
}
//正方形
class Square implements Shape {
public Object clone() {
Square b = null;
try {
b = (Square) super.clone();
} catch (CloneNotSupportedException e) {
System.out.println("拷贝正方形失败!");
}
return b;
}
public void countArea() {
int a = 0;
System.out.print("这是一个正方形,请输入它的边长:");
Scanner input = new Scanner(System.in);
a = input.nextInt();
System.out.println("该正方形的面积=" + a * a + "\n");
}
}
//管理类
class ProtoTypeManager {
private HashMap<String, Shape> ht = new HashMap<String, Shape>();
public ProtoTypeManager() {
ht.put("Circle", new Circle());
ht.put("Square", new Square());
}
public void addshape(String key, Shape obj) {
ht.put(key, obj);
}
public Shape getShape(String key) {
Shape temp = ht.get(key);
return (Shape) temp.clone();
}
}
//具体实现
ProtoTypeManager pm = new ProtoTypeManager();
Shape obj1 = (Circle) pm.getShape("Circle");
obj1.countArea();
Shape obj2 = (Shape) pm.getShape("Square");
obj2.countArea();

这个扩展其实就是使用HashMap来管理,根据key来调用不同的实现,当然还有替换的方案。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。