网站子站怎么做,代理ip地址,品牌vi设计手册案例欣赏,四川建设人员信息查询百日筑基第二十三天-23种设计模式-创建型总汇
前言
设计模式可以说是对于七大设计原则的实现。
总体来说设计模式分为三大类#xff1a;
创建型模式#xff0c;共五种#xff1a;单例模式、简单工厂模式、抽象工厂模式、建造者模式、原型模式。结构型模式#xff0c;共…百日筑基第二十三天-23种设计模式-创建型总汇
前言
设计模式可以说是对于七大设计原则的实现。
总体来说设计模式分为三大类
创建型模式共五种单例模式、简单工厂模式、抽象工厂模式、建造者模式、原型模式。结构型模式共七种适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。行为型模式共十一种策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
23种设计模式的关系图
单例模式
简介
单例模式Singleton Pattern是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类该类负责创建自己的对象同时确保只有单个对象被创建私有的构造器这个类对外提供了唯一一种访问其实例的方式对外只能够直接访问不能实例化此类对象。例如一台计算机上可以连接多台打印机但是这个计算机上的打印程序只能有一个这里就可以通过单例模式来避免两个打印作业同时输出到打印机中即在整个的打印过程中只有一个打印程序的实例。
简单点说单例模式也叫单件模式的作用就是保证在整个应用程序的生命周期中任何时刻单例类的实例都最多只存在一个。单例模式确保某一个类只有一个实例而且自行实例化并向整个系统提供这个实例单例模式。单例模式只应在有真正的“单一实例”需求时才可以使用。
单例的类图如下其中 uniqueInstance 持有唯一的单例实例类方法 getInstance() 用来获取唯一的实例化对象。 Singleton
——————————————————————
-static uniqueInstance
-other Attribute
——————————————————————
static genInstance()()
otherMethods()8 种单例实现方式有点多但有必要都看
【1】饿汉式静态常量优缺点 ● 优点这种写法比较简单就是在类装载的时候就完成实例化。避免了线程同步问题。没有加锁执行效率会提高。 ● 缺点在类装载的时候就完成实例化没有达到 Lazy Loading 的效果。如果从始至终从未使用过这个实例则会造成内存浪费容易产生垃圾对象。 ● 这种方式基于 classload 机制避免了多线程同步问题instance 在类装载时就实例化在单例模式中大多数都是调用 getInstance 方法但是导致类装载的原因有很多种因此通过其他方式或者其他静态方法导致类装载此时初始化 instance就没有达到 Lazy Loading 的效果。
public class SingleTon {//将构造器私有化,防止直接 Newprivate SingleTon(){}//创建好一个私有的 SingleTon 实例private static SingleTon instance new SingleTon();//提供一个 public 的静态方法, 可以返回 instancepublic static SingleTon getInstance() {return instance;}
}
【2】饿汉式静态代码块优缺点 ● 这种方式和上面的方式其实类似只不过将类实例化的过程放在了静态代码块中也是在类装载的时候就执行静态代码块中的代码初始化类的实例。优缺点和上面一样。 ● 结论这种单例模式可用但可能造成内存浪费。
public class SingleTon {//将构造器私有化,防止直接 Newprivate SingleTon(){}//创建好一个私有的 SingleTon 实例private static SingleTon instance;//静态块static {instance new SingleTon();}//提供一个 public 的静态方法, 可以返回 instancepublic static SingleTon getInstance() {return instance;}
}
【3】懒汉式线程不安全优缺点
● 起到了 Lazy Loading 的效果但是只能在单线程下使用。 ● 如果在多线程下一个线程进入if(singleton null)判断语句块还未来得及创建另一个线程也通过了上述判断语句这时便产生了多个实例。所以在多线程环境下不可使用这种方式。 ● 结论在实际开发中不要使用这种方法。
public class SingleTon {//将构造器私有化,防止直接 Newprivate SingleTon(){}//创建好一个私有的 SingleTon 实例private static SingleTon instance;//提供一个 public 的静态方法, 可以返回 instancepublic static SingleTon getInstance() {if(instance null) {instance new SingleTon();}return instance;}
}
【4】懒汉式线程安全同步方法优缺点 ● 解决了线程不安全问题。 ● 效率太低了每个线程在想获得类的实例的时候执行 getInstance() 方法都要进行同步。而其实这个方法只执行一次实例化代码就够了后面的想获得实例直接 return 就够了。方法进行同步效率太低。 ● 结论在实际开发中不推荐使用。
public class SingleTon {//将构造器私有化,防止直接 Newprivate SingleTon(){}//创建好一个私有的 SingleTon 实例private static SingleTon instance;//提供一个 public 的静态方法, 可以返回 instancepublic static synchronized SingleTon getInstance() {if(instance null) {instance new SingleTon();}return instance;}
}
【5】懒汉式线程安全同步代码块优缺点 ● 这种方式本意是想对第四种实现方式的改进因为前面同步方法效率太低 改为同步产生实例化的的代码块。 ● 但是这种同步并不能起到线程同步的作用。跟第3种实现方式遇到的情形一致假如一个线程进入了 if (singleton null) 判断语句块还未来得及往下执行另一个线程也通过了这个判断语句这时便会产生多个实例。 ● 结论在实际开发中不能使用这种方式。
public class SingleTon {//将构造器私有化,防止直接 Newprivate SingleTon(){}//创建好一个私有的 SingleTon 实例private static SingleTon instance;//提供一个 public 的静态方法, 可以返回 instancepublic static SingleTon getInstance() {if(instance null) {//添加同步代码块提高了效率多线程时存在创建的对象不一致风险synchronized(SingleTon.class) {instance new SingleTon();}}return instance;}
}
【7】静态内部类优缺点 ● 这种方式采用了类加载器的机制来保证初始化实例时只有一个线程。 ● 静态内部类方式在 SingleTon 类父类被装载时不会导致内部类被装载也就不会立即实例化属于懒加载类型。当调用 getInstance() 方法时才会装载 SingleTonInstance 类从而完成 SingleTon 的实例化。 ● 类的静态属性只会在第一次加载类的时候初始化所以在这里JVM 帮我们保证了线程的安全在类初始化时别的线程无法进入。 ● 避免了线程不安全利用静态内部类特点实现延迟加载效率高。 ● 结论推荐使用。
public class SingleTon {//将构造器私有化,防止直接 Newprivate SingleTon(){}//在内部内中创建一个对象的实例,当父类 SingleTon 加载时内部类 SingleTonInstance 无需加载private static class SingleTonInstance{private static final SingleTon INSTANCE new SingleTon();}//提供一个 public 的静态方法, 可以返回 SingleTon实例public static SingleTon getInstance() {return SingleTonInstance.INSTANCE;}
}
【8】枚举优缺点 ● 这借助JDK1.5中添加的枚举来实现单例模式。不仅能避免多线程同步问题而且还能防止反序列化重新创建新的对象。 ● 这种方式是Effective Java作者Josh Bloch 提倡的方式 ● 结论推荐使用
enum SingleTon {//当只有一个对象时,就是单例INSTANCE;
}单例模式注意事项和使用场景
【1】单例模式保证了系统内存中该内只存在一个对象节省了系统资源对于一些需要频繁创建和销毁的对象使用单例模式可以提高系统性能。 【2】当想实例化一个单例类的时候必须要记住使用相应的获取对象的方法而不是使用 new。 【3】单例模式使用场景
需要频繁的进行创建和销毁对象创建对象时耗时过多或消耗过多资源既重量级对象但又常使用的对象工具类对象频繁访问数据库或文件的对象比如数据源、session工厂等
工厂模式
简介
工厂模式Factory Pattern是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式它提供了一种创建对象的最佳方式。在工厂模式中我们在创建对象时不会对客户端暴露创建逻辑并且是通过使用一个共同的接口来指向新创建的对象。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单使用的模式。简单工厂模式定义了一个创建对象的类由这个类来封装实例化对象的行为。在软件开发中当我们会用到大量的创建某种、某类或者某批量对象时就会使用到工厂模式。
简单工厂模式案例 【1】定义一个接口 Pizza
package com.yintong.principle.singleresponsibility;
//将Pizza 做成一个接口
public interface Pizza {//准备原材料, 不同的披萨不一样因此我们做成抽象方法public void prepare();
}【2】定义披萨的种类实现 Pizza 接口如下定义了 GREEK、CHEESE 两种披萨。如果后续有新的种类可以实现 Pizza 接口继续添加新的品种。
//希腊披萨
public class GreekPizza implements Pizza{Overridepublic void prepare() {System.out.println( 给希腊披萨 准备原材料 );}
}
//奶酪披萨
public class CheesePizza implements Pizza{Overridepublic void prepare() {System.out.println( 给制作奶酪披萨 准备原材料 );}
}
【3】 创建一个简单的工厂类对象 SimpleFactory
public class SimpleFactory {//传入 orderType种类 返回对应的 Pizza 对象public Pizza createPizza(String orderType) {Pizza pizza null;//使用简单工厂模式if (orderType.equals(greek)) {//希腊披萨pizza new GreekPizza();} else if (orderType.equals(cheese)) {//奶酪披萨pizza new CheesePizza();}return pizza;}
}
【4】在应用代码 OrderPizza 中调用工厂类获取用户需要的披萨对象。
public class OrderPizza {//定义用户要获取的披萨类型private static final String pizza greek;public static void main(String[] args) {//通过工厂获取希腊披萨SimpleFactory simpleFactory new SimpleFactory();//greekPizza 就是我们需要获取的目标披萨Pizza greekPizza simpleFactory.createPizza(pizza);//调用目标披萨的方法greekPizza.prepare();}
}
简单工厂模式的优缺点
优点 1一个调用者想创建一个对象只要知道其名称就可以了。 2扩展性高如果想增加一个产品只要扩展一个工厂类就可以。 3屏蔽产品的具体实现调用者只关心产品接口。
缺点 每增加一个产品时都需要增加一个具体实现类和对象实现工厂使得系统中类的个数成倍增加在一定程度上增加了系统的复杂度同时也增加了系统具体类的依赖。这并不是什么好事。
注意事项 作为一种创建类模式在任何需要生成复杂对象的地方都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式而简单对象特别只需要通过 new 就可以完成创建的对象无需工厂模式。如果使用工厂模式就需要使用工厂类会增加系统的复杂度。
抽象工厂方法模式
需求 在上述的基础上添加了地区。例如用户可以点北京的奶酪披萨北京的胡椒披萨或者伦敦的奶酪披萨伦敦的胡椒披萨。
工厂方法设计模式 1、定义一个 interface工厂的接口 用于创建相关或者依赖关系的对象簇而无需指明具体对象类。 2、从设计层面来看抽象工厂模式就是简单工厂模式的改进或者称为进一步抽象。 3、将工厂抽象成两层AbsFactory抽象工厂和具体实现的工厂子类。程序员可以根据创建对象类型使用对应的工厂子类。这样将单个的简单工厂类变成了工厂簇更有利于代码的维护和扩展。
类图 将简单工厂模式中的工厂类抽象成了一个接口易于后期扩展。 【1】定义工厂类的接口AbsFactory
//一个抽象工厂模式的抽象层(接口)
public interface AbsFactory {//让下面的工厂子类来 具体实现public Pizza createPizza(String orderType);
}【2】让北京和伦敦的工厂类实现此接口与简单工厂类的区别就是实现了 AbsFactory 接口伦敦略
public class BJFactory implements AbsFactory{//更加orderType 返回对应的Pizza 对象public Pizza createPizza(String orderType) {Pizza pizza null;//使用简单工厂模式if (orderType.equals(greek)) {//希腊披萨pizza new GreekPizza();} else if (orderType.equals(cheese)) {//奶酪披萨pizza new CheesePizza();}return pizza;}
}【3】在 Order 订单应用中与接口 AbsFactory 进行组合。
public class OrderPizza {AbsFactory factory;//定义构造器public OrderPizza(AbsFactory factory){this.factory factory;}//定义用户要获取的披萨类型可以定义一个变量从客户端传入private static final String pizza greek;public void main(String[] args) {//greekPizza 就是我们需要获取的目标披萨Pizza greekPizza factory.createPizza(pizza);//调用目标披萨的方法greekPizza.prepare();}
}
工厂模式在 JDK-Calendar 类中的应用
//1、调用 Calendar 对象
Calendar instance Calendar.getInstance();
//2、进入 Calendar.getInstance() 方法
public static Calendar getInstance()
{return createCalendar(TimeZone.getDefault(),Locale.getDefault(Locale.Category.FORMAT));
}
//3、进入 createCalendar 方法
private static Calendar createCalendar(TimeZone zone,Locale aLocale){CalendarProvider provider LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale).getCalendarProvider();if (provider ! null) {try {return provider.getInstance(zone, aLocale);} catch (IllegalArgumentException iae) {// fall back to the default instantiation}}Calendar cal null;if (aLocale.hasExtensions()) {String caltype aLocale.getUnicodeLocaleType(ca);if (caltype ! null) {//这里就是我们要重点查看的部分根据用户需求创建Calendar 对象switch (caltype) {case buddhist:cal new BuddhistCalendar(zone, aLocale);break;case japanese:cal new JapaneseImperialCalendar(zone, aLocale);break;case gregory:cal new GregorianCalendar(zone, aLocale);break;}}}return cal;
}
工厂模式小结
1工厂模式的意义 将实例化对象的代码提取出来放到一个类中统一管理和维护达到和主项目的依赖关系的解耦。从而提高项目的扩展和维护性。 2设计模式依赖抽象原则 创建对象实例时不要直接 new 类而是把这个 new 类的动作放在一个工厂的方法中并返回。不要让类继承具体类而是继承抽象类或者实现 interface接口。不要覆盖基类中已经实现的方法。
建造者模式
简介
建造者模式Builder Pattern 使用简单的对象一步一步构建成一个复杂的对象。这种设计模式属于创建者模式它提供了一种创建对象的最佳方式。一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。例如计算机是由 CPU、主板、内存、硬盘、显卡、机箱、显示器、键盘、鼠标等部件组装而成的采购员不可能自己去组装计算机而是将计算机的配置要求告诉计算机销售公司计算机销售公司安排技术人员去组装计算机然后再交给要买计算机的采购员。
以上所有这些产品都是由多个部件构成的各个部件可以灵活选择但其创建步骤都大同小异。这类产品的创建无法用前面介绍的工厂模式描述只有建造者模式可以很好地描述该类产品的创建。
建造者模式 又叫生成器模式是一种对象构建模式。它可以将复杂对象的建造过程抽象出来抽象类别使这个抽象过程的不同实现方法可以构造出不同表现属性的对象。建造者模式它允许用户只通过指定复杂对象的类型和内容就可以构建它们用户不需要知道内部的具体构建细节。建造者模式主要解决在软件系统中当面临一个复杂对象的创建工作时其通常由各个部分的子对象用一定的算法构成由于需求的变化这个复杂对象的各个部分经常面临剧烈的变化但是将它们组合在一起的算法却相对稳定。主要适用于一些基本部件不会变而其组合经常变化的情况。主要是将变与不变进行分离去肯德基汉堡、可乐、薯条、炸鸡翅等是不变的而其组合是经常变化的生成出所谓的套餐。
建造者模式的四个角色
1Product产品角色 包含多个组成部件的复杂对象(产品对象)。 2Builder抽象建造者 创建一个包含 Product 各个子部件的抽象方法或接口通常还包含了一个返回复杂产品的方法。 3ConcreteBuilder具体建造者 实现 Builder 接口构建和装备各个子部件的具体实现。 4Director指挥者 构建一个使用 Builder 接口的对象。它主要作用是用于创建一个复杂的对象。在指挥者中不涉及具体产品的信息。主要分两个作用一是隔离客户与对象的生产过程二是负责控制对象的生产过程。
建造者模式的注意事项和细节
1客户端不必知道产品内部组成的细节将产品本身与产品的创建过程解耦使得相同的创建过程可以创建不同的产品对象。 2每一个具体建造者都相对独立因此可以方便的替换或者新增具体建造者用户使用不同的具体建造者即可得到不同的产品对象。 3可以更加精准的控制产品的创建过程。将复杂产品的创建步骤分解在不同的方法中使得创建过程更加清晰也更方便使用程序来控制创建过程。 4增加新的具体建筑者无需修改原有类库代码指挥者类针对抽象建造者类编程系统扩展方便。符合 OCP 原则。 5建造者模式创建的产品具有较多的共同点其组成部分相似如果产品之间的差异性很大则不适合建造者模式因此其使用范围受到一定的限制。 6如果产品的内部变化复杂可能会导致需要定义很多具体建造者内来实现这种变化导致系统变得庞大因此这种情况下考虑是否选择建造者模式。 7抽象工厂模式 VS 建造者模式抽象工厂模式实现对产品家族的创建一个产品家族就是一系列产品。具有不同分类维度的产品组合采用抽象工厂模式不需要关系构建过程只关系产品由什么工厂生成即可。而建造者模式则是要求按照指定的蓝图建造产品它主要目的是通过组装零配件而产生一个新产品。
建造者模式原理类图 建造者模式案例
【1】创建 Product 产品角色
public class Product {private String CPU;//主板 mainboardprivate String mainboard;//内存 memoryprivate String memory;//.....略//生成get set 方法 略
}
【2】抽象建造者对象
public abstract class Builder {//组合 产品对象protected Product product new Product();//抽象方法public abstract void buildCpu();public abstract void buildMainboard();public abstract void buildMemory();//返回一个产品对象public Product getResult() {return product;}
}
【3】具体建造者对象一般会有多个这种对象都实现 Builder 抽象类。
public class ConcreteBuilder_huawei extends Builder{Overridepublic void buildCpu() {product.setCPU(华为CPU);}Overridepublic void buildMainboard() {product.setMainboard(华为主板);}Overridepublic void buildMemory() {product.setMemory(华为内存);}}
【4】指挥者类主要构建组装的流程返回的是产品对象
public class Director {//需要将抽象类聚合进来Builder builder null;//创建一个构造器 调用时传入具体的实现类public Director(Builder builder) {this.builder builder;}//添加set 方法 用户可以通过此方法修改已有的 建造者对象public void setBuilder(Builder builder) {this.builder builder;}//笔记本的组成流程 返回的是产品类public Product pack_pc() {builder.buildMainboard();builder.buildCpu();builder.buildMemory();return builder.getResult();}
}
【5】客户端通过指挥者类调用需要的品牌电脑
public class Client {public static void main(String[] args) {//创建需要的电脑子部件——例如我们要组装的是 华为ConcreteBuilder_huawei huawei new ConcreteBuilder_huawei();//调用指挥者类将需要的品牌传入根据控制着中的流程进行组装Director director new Director(huawei);//调用组装方法返回产品Product pack_pc director.pack_pc();//查看输入的结果System.out.println(pack_pc.toString());//结果为Product [CPU华为CPU, mainboard华为主板, memory华为内存]}
}源码分析StringBuilder
【1】java.lang.StringBuilder中的建造者模式
public class OrginBuilder {public static void main(String[] args) {StringBuilder builder new StringBuilder(hello);builder.append(world);}
}【2】进入 append 方法会发现 StringBuilder 类即就是我们所说的指挥者。建造方法的具体实现是由 AbstractStringBuilder 实现。
Override
public StringBuilder append(String str) {super.append(str);return this;
}
【3】进入 AbstractStringBuilder 类实现了 Appendable 接口方法此类已是建造者只是不能实例化。
public AbstractStringBuilder append(String str) {if (str null)return appendNull();int len str.length();ensureCapacityInternal(count len);str.getChars(0, len, value, count);count len;return this;
}
【4】Appendable 接口定义了多个 append 方法抽象方法既 Appendle 为抽象建造者定义了抽象方法。
public interface Appendable {Appendable append(CharSequence csq) throws IOException; ......
}
原型模式
简介
原型模式Prototype Pattern 是用于创建重复对象同时又能保证性能。这种类型的设计模式属于创建型模式它提供了一种创建对象的最佳方式。这种模式是实现了一个原型接口该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时则采用这种模式。
思想 Java 中 Object 类是所有类的根类Object 类提供了一个 clone() 方法该方法可以将一个 Java 对象复制一份但是需要实现 clone 的 Java 类必须要实现一个接口 Cloneable该接口表示该类能够复制且具有复制的能力原型模式。
原型模式用原型实例指定创建对象的种类并且通过拷贝这些原型创建新的对象。原型模式是一种创建型设计模式允许一个对象再创建另外一个可定制的对象无需知道如何创建的细节。工作原理是通过将一个原型对象传给那个要发动创建的对象这个要发动创建的对象通过请求原型对像拷贝它们自己来实现创建及对象的clone()。
原理结构图说明 1Prototype原型类声明一个克隆自己的接口 clone。 2ConcretePrototype具体的原型类实现一个克隆自己的操作。 3Client 让一个原型对象克隆自己从而创建一个新的对象相当于属性。 原型模式案例分析
【1】克隆类需要实现 Cloneable 重写 clone 方法。
package com.yintong.principle.singleresponsibility;
//写一个手机的克隆类
public class ConcretePrototype implements Cloneable{//名称private String name;//号码private Long number;//构造器public ConcretePrototype(String name, Long number) {super();this.name name;this.number number;}Overridepublic String toString() {return ConcretePrototype [name name , number number ];}// 克隆用到的主要部分Overrideprotected Object clone() throws CloneNotSupportedException {ConcretePrototype ConcretePrototype null;try {ConcretePrototype (ConcretePrototype) super.clone();}catch (Exception e) {System.out.println(e.getMessage());}return ConcretePrototype;}
}
【2】客户端调用 clone 方法实现原型模式。
public class Client {public static void main(String[] args) throws CloneNotSupportedException {//创建一个对象ConcretePrototype prototype new ConcretePrototype(华为, new Long(1568889932));//通过原型模式完成对象的创建 克隆ConcretePrototype p2 (ConcretePrototype)prototype.clone();}
}
Spring 中的应用
【1】当 scope 配置为 prototype 时表示原型模式。 !-- 这里我们的 scopeprototype 即 原型模式来创建 --bean idid01 classcom.atguigu.spring.bean.Monster scopeprototype/
【2】查看底层调用
else if (mbd.isPrototype()) {// Its a prototype - create a new instance.Object prototypeInstance null;try {beforePrototypeCreation(beanName);prototypeInstance createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}// *** 创建一个代理类 ***bean getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
浅拷贝
● 对于数据类型是基本数据类型的成员变量浅拷贝会直接进行值传递也就是将该属性值复制一份给新对象。 ● 对于数据类型是引用类型的成员变量比如说成员变量是某个数组、某个类的对象等那么浅拷贝会进行引用传值也就是只是将成员变量的引用值内存地址复制一份给新对象。因为实际上两个对象的该成员变量都指向同一个实例。在这种情况下在一个对象中修改该成员变量会影响到另一个对象的该成员变量值。 ● 浅拷贝是使用默认的 clone() 方法来实现。
深拷贝
● 复制对象的所有基本数据类型的成员变量值。 ● 为所有引用数据类型的成员变量申请存储空间并复制每个引用数据类型成员变量所引用的对象直到该对象可达的所有对象。也就是说对象进行深拷贝要对整个对象进行拷贝。 ● 深拷贝的实现方式有两种第一种是重写 clone 方法来实现深拷贝第二种是通过序列化实现深拷贝也是推荐的一种。
深拷贝的两种实现方法
【1】通过调用引用类型的克隆方法实现深拷贝。缺点就是当引用类型多时不建议采用。
public class DeepClone implements Cloneable{//基本数据类型private String name;//引用数据类型private Spare spare;//重写clone方法调用引用类型的克隆方法Overrideprotected Object clone() throws CloneNotSupportedException {DeepClone deepClone null;deepClone (DeepClone)super.clone();//克隆引用数据类型deepClone.spare (Spare) spare.clone();return deepClone;}
}
【2】通过序列化的方式实现深拷贝也是建议使用的方法。
public class DeepClone implements Serializable{/*** 序列化 ID*/private static final long serialVersionUID 1L;//数据类型 略。。。。//重写clone方法调用引用类型的克隆方法protected Object deepClone(){ByteArrayOutputStream BOStream null;ObjectOutputStream OOSream null;ByteArrayInputStream BIStream null;ObjectInputStream OIStream null;try {//序列化BOStream new ByteArrayOutputStream();OOSream new ObjectOutputStream(BOStream);//将当前对象写入流中OOSream.writeObject(this);//反序列化BIStream new ByteArrayInputStream(BOStream.toByteArray());OIStream new ObjectInputStream(BIStream);DeepClone deepClone (DeepClone) OIStream.readObject();return deepClone;} catch (Exception e) {e.printStackTrace();return null;}finally {try {BOStream.close();OOSream.close();BIStream.close();OIStream.close();} catch (Exception e2) {e2.printStackTrace();}}}
}
原型模式的注意事项和细节
1创建新的对象比较复杂时可以利用原型模式简化对象的创建过程同时也能够提高效率。 2不用重新初始化对象而是动态地获得对象运行时的状态。 3如果原始对象发生变化增加或者减少属性其他克隆对象也会发生变化无需修改代码。 4在实现深克隆的时候可能需要比较复杂的代码。 5缺点需要为每一个配置类配置一个克隆方法这对全新的类来说不是很难,但对已有的类进行改造时需要修改其源代码违背了 ocp 原则。