java设计模式---创建者模式

GOF(23种设计模式)分为三大类:

创建型模式:单例模式、工厂模式、抽象工厂模式、建造者模式、原型模式

结构型模式:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式

行为模式:模板方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式、职责链模式、访问者模式。

一、创建者模式:都是用来帮助我们创建对象的

1.单例模式

  保证一个类只有一个实例,并且提供一个访问该实例的全局访问点。

优点:

1)由于单例模式只生成一个实例,减少了系统性能的开销,当一个对象的产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可以通过在应用启动时产生一个单例对象,然后永久驻留内存的方式来解决。

2)由于单例模式可以在系统设置全局的访问点,优化环境共享资源访问,例如可以设计一个单例类,负责所有数据表的映射处理。

常见五种单例模式实现方式:

1)饿汉式(线程安全,调用效率高。但是,不能延时加载。)

/*
 * 测试饿汉式单例模式
 * */
public class SingletonDemo1 {
    //声明私有静态属性,同时创建对象
    //类初始化时,就会加载这个对象(没有延时加载的优势)!
    // 由于加载类时,天然的是线程安全的
    private static SingletonDemo1 instance = new SingletonDemo1();
    //构造器私有化
    private SingletonDemo1() {
    }
    //创建一个对外公开的静态方法访问该静态变量
    //方法没有同步调用效率高
    public static SingletonDemo1 getInstance() {
        return instance;
    }
}

2)懒汉式(线程安全,调用效率不高。但是,可以延时加载。)

/*
 * 测试懒汉式单例模式
 * */
public class SingletonDemo2 {
    //声明私有静态属性
    private static SingletonDemo2 instance;
    //构造器私有化
    private SingletonDemo2() {

    }
    //创建一个对外公开的静态方法访问该静态变量
    //延时加载,懒加载,真正用的时候才加载
    //资源效率高了,但是并发时调用效率较低。
    // 因为方法synchronized同步,并发时需要等待调用getInstance()方法
    public static synchronized SingletonDemo2 getInstance() {
        if (null == instance) {
            instance = new SingletonDemo2();
        }
        return instance;
    }
}

3)双重检测锁式(由于编译器优化原因和JVM底层内部模型原因,偶尔会出问题,不建议使用)

/*
 * 双重检测锁实现单例模式
 * */
public class SingletonDemo3 {
    private static SingletonDemo3 instance = null;

    private SingletonDemo3() {

    }

    public static SingletonDemo3 getInstance() {
        if (instance == null) {
            SingletonDemo3 sc;
            synchronized (SingletonDemo3.class) {
                sc = instance;
                if (sc == null) {
                    synchronized (SingletonDemo3.class) {
                        if (sc == null) {
                            sc = new SingletonDemo3();
                        }
                    }
                    instance = sc;
                }
            }
        }
        return instance;
    }
}

4)静态内部类式(线程安全,调用效率高,但是,可以延时加载)

/*
* 静态内部类实现单例模式(也是一种懒加载方式)
* 外部类没有static属性,则不会像饿汉式那样立即加载对象
* */
public class SingletonDemo4 {
    private SingletonDemo4() {

    }
    private static class SingletonClassIntance{
        private static final SingletonDemo4 instance = new SingletonDemo4();
    }
   //只有真正调用了getInstance()才会加载静态内部类。
     //加载类是线程安全的。
     // instancestatic final类型,保证了内存中只有一个这样的实例存在,而且只能被赋值一次,从而保证了线程安全性。
     //兼并了并发高效调用和延迟加载的优势
     public static SingletonDemo4 getInstance() {
        return SingletonClassIntance.instance;
    }
}

5)枚举单例(线程安全,调用效率高。但是,不能延时加载。)

优点:<1>实现简单

   <2>枚举本身就是单例模式。由JVM从根本上提供保证!避免通过反射和反序列化的漏洞

缺点:无延时加载

/*
 * 使用枚举实现单例模式 枚举类天然是单例的
 * 没有延时加载
 * */
public enum SingletonDemo5 {
    //定义一个枚举元素,本身就是单例对象,它就代表了Singleton的一个实例
    INSTANCE;
    //单例可以有自己的操作
    public void SingletonOperation() {
        //功能处理
    }
}

2.如何选用?

单例对象 占用资源少,不需要 延时加载

    枚举式 好于 饿汉式

单例对象 占用资源大,需要 延时加载

    静态内部类 好于 懒汉式

问题:

1)反射可以破解上面几种(不包含枚举式)实现方式(可以在构造方法中手动抛出异常控制)

SingletonDemo6 s1 = SingletonDemo6.getInstance();
SingletonDemo6 s2 = SingletonDemo6.getInstance();

System.out.println(s1);
System.out.println(s2);

//通过反射的方式直接调用私有构造器
Class<SingletonDemo6> clazz = (Class<SingletonDemo6>) Class.forName("cn.hyy.test.pattern.singlePattern.SingletonDemo6");
Constructor<SingletonDemo6> c = clazz.getDeclaredConstructor(null);
c.setAccessible(true);
SingletonDemo6 s3 = c.newInstance();
SingletonDemo6 s4 = c.newInstance();

System.out.println(s3);
System.out.println(s4);

在构造方法中手动抛出异常控制

/*
* 测试懒汉式单例模式(如何防止反射和反序列化漏洞)
* */
public class SingletonDemo6 {
    //声明私有静态属性
    private static SingletonDemo6 instance;
    //构造器私有化
    private SingletonDemo6() {
        if (instance != null) {
            throw new RuntimeException();
        }
    }
    //创建一个对外公开的静态方法访问该静态变量
    //延时加载,懒加载,真正用的时候才加载
    //资源效率高了,但是并发时调用效率较低。
    // 因为方法synchronized同步,并发时需要等待调用getInstance()方法
    public static synchronized SingletonDemo6 getInstance() {
        if (null == instance) {
            instance = new SingletonDemo6();
        }
        return instance;
    }

}

2)反序列化可以破解上面几种(不包含枚举式)实现方式

   可以通过定义readResolve()防止获得不同对象

    --反序列化时,如果对象所在类定义了readResolve(),(实际是一种回调),定义返回哪个对象。

//通过反序列化方式构造多个对象
FileOutputStream fos = new FileOutputStream("/home/deepin/Desktop/test/aa.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(s1);
oos.close();
fos.close();

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("/home/deepin/Desktop/test/aa.txt"));
SingletonDemo6 s3 = (SingletonDemo6) ois.readObject();
System.out.println(s3);
/*
* 测试懒汉式单例模式(如何防止反射和反序列化漏洞)
* */
public class SingletonDemo6 implements Serializable {
   //声明私有静态属性
    private static SingletonDemo6 instance;
   //构造器私有化
    private SingletonDemo6() {
        if (instance != null) {
            throw new RuntimeException();
        }
    }
  //创建一个对外公开的静态方法访问该静态变量
    //延时加载,懒加载,真正用的时候才加载
    //资源效率高了,但是并发时调用效率较低。
    // 因为方法synchronized同步,并发时需要等待调用getInstance()方法
    public static synchronized SingletonDemo6 getInstance() {
        if (null == instance) {
            instance = new SingletonDemo6();
        }
        return instance;
    }

 //反序列化时,如果定义了readResolve(),则直接返回此方法指定的对象。而不需要单独再创建对象!
 public Object readResolve() throws ObjectStreamException {
       return instance;
    }
}

多线程环境下五种创建单例模式的效率


CountDownLatch

      同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待

   countDown() 当前线程调此方法,则计数减一(建议放在finally里执行)

       await(),调用此方法会一直阻塞当前线程,直到计时器的值为0

/*
 * 测试多线程环境下五种创建单例模式的效率
 * */
public class Client3 {

    public static void main(String[] args) throws InterruptedException {

        long start = System.currentTimeMillis();
        CountDownLatch countDownLatch =  new CountDownLatch(10);

        for (int i = 0; i <10 ; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < 1000000; i++) {
                        Object o = SingletonDemo2.getInstance();
                    }
                    countDownLatch.countDown();
                }
            }).start();
        }
        countDownLatch.await();  //main线程阻塞,直到计数器变为0,才会继续往下执行
           long end = System.currentTimeMillis();
        System.out.println("总耗时:" + (end - start)+"");
    }
}

2.工厂模式

实现了创建者和调用者的分离

详细分类:

  1)简单工厂模式

  2)工厂方法模式

  3)抽象工厂模式

面向对象设计的六大基本原则:

  SRP(单一职责原则,Single Responsibility Principle):就一个类而言,应该仅有一个引起它变化的原因。简单来说,一个类中应该是一组相关性很高的函数、数据的封装。

  OCP(开闭原则,Open-Closed Principle):一个软件的实体应当对扩展开放,对修改关闭

         LSP(里式替换原则,Liskov Substitution Principle):所有引用基类的地方必须能透明地使用其子类的对象。通俗点讲,只要父类能出现的地方子类就可以出现,而且替换为子类也不会产生任何错误或异常,使用者可能根本就不需要知道是父类还是子类。但是,反过来就不行了,有子类出现的地方,父类未必就能适应。

     DIP(依赖倒转原则,Dependence Inversion Principle):要针对接口编程,不要针对实现编程

     ISP(接口隔离原则,Interface Segregation Principles):客户端不应该依赖它不需要的接口

         LoD(迪米特法则,Law of Demeter):只与你直接的朋友通信,而避免和陌生人通信

1)简单工厂模式

            也叫静态工厂模式,就是工厂类一般使用静态方法,通过接收的系数的不同来返回不同的对象实例。

   对于增加新产品无能为力!不修改代码的话,是无法扩展的(违反开闭原则)

public interface Car {
    void run();
}
public class Audi implements Car {

    @Override
    public void run() {
        System.out.println("奥迪在跑");
    }
}
public class Byd implements Car {
    @Override
    public void run() {
        System.out.println("比亚迪在跑");
    }
}

<1>没有简单工厂的情况下

/*
* 没有工厂模式的情况下
* */
public class Client01 {
    public static void main(String[] args) {
        Car c1 = new Audi();
        Car c2 = new Byd();

        c1.run();
        c2.run();
    }
}

UML类图


<2>在有简单工厂的情况下,调用者只需要和工厂打交道

public class CarFactory{
    public static Car createCar(String type) {
        if ("奥迪".equals(type)) {
            return new Audi();
        } else if ("比亚迪".equals(type)) {
            return new Byd();
        } else {
            return null;
        }
    }
}

或者

public class CarFactory2 {
    public static Car createAudi() {
        return new Audi();
    }

    public static Car createByd() {
        return new Byd();
    }
}
UML类图


2)工厂方法模式

 --为了避免简单工厂的缺点,不完全满足OCP

   --工厂方法模式和简单工厂模式最大不同完全在于,简单工厂模式只有一个(对应一个项目或者独立模块而言)工厂类,而工厂方法模式有一组实现了相同接口的工厂类。

public interface Car {
    void run();
}

public class Audi implements Car {
    @Override
    public void run() {
        System.out.println("奥迪在跑");
    }
}
public class Byd implements Car {
    @Override
    public void run() {
        System.out.println("比亚迪在跑");
    }
}
public class Benz implements Car {
    @Override
    public void run() {
        System.out.println("奔驰在跑");
    }
}
public interface CarFactory {
    Car createCar();
}
public class AudiFactory implements CarFactory {
    @Override
    public Car createCar() {
        return  new Audi();
    }
}
public class BydFactory implements CarFactory {
    @Override
    public Car createCar() {
        return new Byd();
    }
}
public class BenzFactory implements CarFactory {
    @Override
    public Car createCar() {
        return new Benz();
    }
}
public class Client {
    public static void main(String[] args) {
        Car c1 = new AudiFactory().createCar();
        Car c2 = new BydFactory().createCar();
        c1.run();
        c2.run();
    }
}

简单工厂模式和工厂方法模式比较:

1>结构复杂度

  简单工厂模式占优,简单工厂模式只需要一个工厂类,而工厂方法模式的工厂类会随着产品类的个数增加而增加,从而增加了结构复杂度。

2>代码复杂度

  代码复杂度和结构复杂度是一对矛盾。简单工厂模式在结构方面相对简洁,那么在代码方面肯定比工厂方法模式复杂的了。简单工厂模式的工厂类会随着产品类的个数增加需要增加很多方法(或代码),而工厂方法模式每个具体工厂类只完成单一任务,代码简洁

3>客户端编程难度

  工厂方法模式虽然在工厂类结构中引入接口从而满足了OCP,但是在客户端编码中需要对工厂类进行实例化。而简单工厂模式的工厂类是个静态类,在客户端无需实例化,这无疑是个吸引人的优点。

4>管理上的难度

这是个关键的问题

  首先先谈扩展,工厂方法模式完全满足OCP,即它有非常良好的的扩展性。那是否说明了简单工厂模式就没有扩展性了呢?答案是否定的,简单工厂模式同样具备良好的扩展性--扩展的时候仅需要修改少量代码(修改工厂类的代码)就可以满足扩展性的要求了,尽管没有完全满足OCP,但我们不需要太拘泥于设计理论。

  然后从维护性的角度分析下,假如某个具体产品类需要进行一定的修改,很可能需要修改对应的工厂类。当同时需要修改多个产品类的时候,对工厂类的修改变得相当麻烦。反而简单工厂模式没有这些麻烦,当多个产品类需要修改时,简单工厂模式仍然仅仅需要修改唯一的工厂类

根据设计理论建议:工厂方法模式,但实际上,我们一般都用简单工厂模式

3)抽象工厂模式

--用来生产不同产品族的全部产品(对于新增加的产品,无能为力;支持增加产品族)

--抽象工厂模式是工厂方法模式的升级版本,在有多个业务品种、业务、分类时,通过抽象工厂模式产生需要的对象是一种非常好的解决方式。


public interface Engine {
    void run();

    void start();
}

class LuxuryEngine implements Engine {

    @Override
    public void run() {
        System.out.println("转得快");
    }

    @Override
    public void start() {
        System.out.println("启动快,可以自动启停");

    }
}
class LowEngine implements Engine {

    @Override
    public void run() {
        System.out.println("转得慢");
    }

    @Override
    public void start() {
        System.out.println("启动慢");

    }
}
public interface Seat {
    void massage();
}

class LuxurySeat implements Seat {

    @Override
    public void massage() {
        System.out.println("可以自动按摩");
    }
}
class LowSeat implements Seat {

    @Override
    public void massage() {
        System.out.println("不能按摩");
    }
}
public interface Tyre {
    void revolve();
}

class LuxuryTyre implements Tyre {

    @Override
    public void revolve() {
        System.out.println("旋转不磨损");
    }
}

class LowTyre implements Tyre {

    @Override
    public void revolve() {
        System.out.println("旋转磨损快");
    }
}
public interface CarFactory {
    Engine createEngine();
    Seat createSeat();
    Tyre createTyre();
}
public class LuxuryCarFactory implements CarFactory {

    @Override
    public Engine createEngine() {
        return new LuxuryEngine();
    }

    @Override
    public Seat createSeat() {
        return new LuxurySeat();
    }

    @Override
    public Tyre createTyre() {
        return new LuxuryTyre();
    }
}
public class LowCarFactory implements CarFactory {
    @Override
    public Engine createEngine() {
        return new LowEngine();
    }

    @Override
    public Seat createSeat() {
        return new LowSeat();
    }

    @Override
    public Tyre createTyre() {
        return new LowTyre();
    }
}
public class Client {
    public static void main(String[] args) {
        CarFactory factory = new LuxuryCarFactory();
        Engine e = factory.createEngine();
        Seat seat = factory.createSeat();
        Tyre tyre = factory.createTyre();
        e.run();
        e.start();

        CarFactory factory1 = new LowCarFactory();
        Engine e1 = factory1.createEngine();
        e1.run();
        e1.start();

    }
}


3.建造者模式

本质:

 --分离对象子组件的单独构造(由Buider来负责)和装配(由Director负责)。从而可以构造出复杂的对象。这个模式适用于:某个对象的构建过程复杂的情况下使用。

 --由于实现构造和装配的解耦。不同的构造器,相同的装配,也可以做出不同的对象;相同的构造器,不同的装配顺序也可以做出不同的对象。也就是实现了构建算法、装配算法的解耦,实现了更好的复用。

public class AirShip {
    private OrbitalModule orbitalModule;//轨道舱
    private Engine engine;   //发动机
    private EscapeTower escapeTower; //逃逸塔

    public void launch() {
        System.out.println("发射");
    }

    public OrbitalModule getOrbitalModule() {
        return orbitalModule;
    }

    public void setOrbitalModule(OrbitalModule orbitalModule) {
        this.orbitalModule = orbitalModule;
    }

    public Engine getEngine() {
        return engine;
    }

    public void setEngine(Engine engine) {
        this.engine = engine;
    }

    public EscapeTower getEscapeTower() {
        return escapeTower;
    }

    public void setEscapeTower(EscapeTower escapeTower) {
        this.escapeTower = escapeTower;
    }
}

class OrbitalModule{
    private String name;

    public OrbitalModule(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

class Engine{
    private String name;

    public Engine(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

class EscapeTower {
    private String name;

    public EscapeTower(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
public interface AirShipBuider {

    Engine buiderEngine();

    OrbitalModule buiderOrbitalModule();

    EscapeTower buiderEscapeTower();
}
public class SxtAirShipBuider implements AirShipBuider {

    @Override
    public Engine buiderEngine() {
        System.out.println("构建发动机");
        return new Engine("尚学堂牌发动机");
    }

    @Override
    public OrbitalModule buiderOrbitalModule() {
        System.out.println("构建轨道舱");
        return new OrbitalModule("尚学堂牌轨道舱");
    }

    @Override
    public EscapeTower buiderEscapeTower() {
        System.out.println("构建逃逸塔");
        return new EscapeTower("尚学堂牌逃逸塔");
    }
}
public interface AirShipDirector {
    AirShip directorAirShip();  //组装飞船对象
}
public class SxtAirShipDirector implements AirShipDirector {

    private AirShipBuider buider;

    public SxtAirShipDirector(AirShipBuider buider) {
        this.buider = buider;
    }

    @Override
    public AirShip directorAirShip() {

        Engine e=buider.buiderEngine();
        OrbitalModule o=buider.buiderOrbitalModule();
        EscapeTower et = buider.buiderEscapeTower();
        //装配成飞船
           AirShip ship = new AirShip();
        ship.setEngine(e);
        ship.setEscapeTower(et);
        ship.setOrbitalModule(o);
        return ship;
    }
}
public class Client {
    public static void main(String[] args) {

        AirShipDirector director = new SxtAirShipDirector(new SxtAirShipBuider());
        AirShip ship = director.directorAirShip();
        System.out.println(ship.getEngine().getName());
        System.out.println(ship.getEscapeTower().getName());
        System.out.println(ship.getOrbitalModule().getName());
        ship.launch();
    }
}


4.原型模式

--通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。

--就是java中的克隆技术,以某个对象为原型,复制出新的对象。显然,新的对象具备原型对象的特点

--优势有:效率高(直接克隆,避免了重新执行构造过程步骤。)

--克隆类似于new,但是不同于new。new创建新的对象属性采用的是默认值。克隆出的对象的属性完全和原型对象相同。并且克隆出的新对象改变不会影响原型对象。然后再修改克隆对象的值。

1>原型模式的实现

--Cloneable接口和clone方法

--Prototype模式中实现起来最困难的地方就是内存复制操作,所幸在java中提供了clone()方法替我们做了绝大部分事情


2>浅复制

public class Sheep implements Cloneable {
    private String sname;
    private Date birthday;

    public String getSname() {
        return sname;
    }

    public void setSname(String sname) {
        this.sname = sname;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public Sheep(String sname, Date birthday) {
        this.sname = sname;
        this.birthday = birthday;
    }

    public Sheep() {

    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Object obj = super.clone();//直接调用object对象的clone()方法
        return obj;
    }
}
/*
* 测试原型模式(浅克隆)
* */
public class Client {
    public static void main(String[] args) throws CloneNotSupportedException {
        Date date= new Date(1222232);
        Sheep s1 = new Sheep("少利", date);
        Sheep s2 = (Sheep) s1.clone();
        System.out.println(s1);
        System.out.println(s1.getSname());
        System.out.println(s1.getBirthday());
        date.setTime(556344552); //修改出生日期,也会修改s2的出生日期
        System.out.println(s1.getBirthday());


        s2.setSname("多利");
        System.out.println(s2);
        System.out.println(s2.getSname());
        System.out.println(s2.getBirthday());
    }
}

3>深复制

public class Sheep2 implements Cloneable {
    private String sname;
    private Date birthday;

    public String getSname() {
        return sname;
    }

    public void setSname(String sname) {
        this.sname = sname;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public Sheep2(String sname, Date birthday) {
        this.sname = sname;
        this.birthday = birthday;
    }

    public Sheep2() {

    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Object obj = super.clone();//直接调用object对象的clone()方法
                   //添加如下代码实现深复制
                   Sheep2 s = (Sheep2) obj;
        s.birthday = (Date) this.birthday.clone();//把属性也进行克隆
                  return obj;
    }
}
/*
* 原型模式(深复制)
* */
public class Client2 {
    public static void main(String[] args) throws CloneNotSupportedException {

        Date date= new Date(1222232);
        Sheep2 s1 = new Sheep2("少利", date);
        Sheep2 s2 = (Sheep2) s1.clone(); //实现深复制,s2对象的birthday是一个新对象
                  System.out.println(s1);
        System.out.println(s1.getSname());
        System.out.println(s1.getBirthday());
        date.setTime(556344552); //此时不会修改s2的出生日期
        System.out.println(s1.getBirthday()); 

                  s2.setSname("多利");
        System.out.println(s2);
        System.out.println(s2.getSname());
        System.out.println(s2.getBirthday());

    }
}

4>使用序列化和反序列化实现深复制

--在Sheep类记得实现Serializable接口

/*
 * 原型模式(深复制,使用序列化和反序列化的方式实现深复制)
 * */
public class Client3 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {

        Date date= new Date(1222232);
        Sheep s1 = new Sheep("少利", date);
        System.out.println(s1);
        System.out.println(s1.getSname());
        System.out.println(s1.getBirthday());

        //使用序列化和反序列化的方式实现深复制
                   ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);

        oos.writeObject(s1);
        byte[] bytes = bos.toByteArray();

        ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
        ObjectInputStream ois = new ObjectInputStream(bis);

        Sheep s2 = (Sheep) ois.readObject();

        date.setTime(556344552);//修改出生日期,也会修改s2的出生日期
                  System.out.println(s1.getBirthday());


        s2.setSname("多利");
        System.out.println(s2);
        System.out.println(s2.getSname());
        System.out.println(s2.getBirthday());
    }
}

5>new方式创建对象和clone方式创建对象的效率差异

/*
* 测试普通new方法创建对象和clone方式创建对象的效率差异
* 如果需要短时间创建大量对象,并且new的过程比较耗时。则可以考虑使用原型模式!
* */
public class Client4 {

    public static void testNew(int size) {
        long start = System.currentTimeMillis();
        for (int i = 0; i < size; i++) {
            Laptop t = new Laptop();
        }

        long end = System.currentTimeMillis();
        System.out.println("new方式创建耗时:"+(end-start));
    }

    public static void testClone(int size) throws CloneNotSupportedException {
        long start = System.currentTimeMillis();
        Laptop t = new Laptop();
        for (int i = 0; i < size; i++) {
            Laptop temp = (Laptop) t.clone();
        }

        long end = System.currentTimeMillis();
        System.out.println("clone方式创建耗时:" + (end - start));
    }


    public static void main(String[] args) throws CloneNotSupportedException {
        testNew(1000);
        testClone(1000);

    }

}

class Laptop implements Cloneable{  //笔记本电脑
    public Laptop() {

        try {
            Thread.sleep(10);  //模拟创建对象耗时的过程
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Object obj = super.clone();//直接调用object对象的clone()方法
        return obj;
    }
}

开发中的应用场景:

--原型模式很少单独出现,一般是和工厂方法模式一起出现。通过clone的方法创建一个对象,然后由工厂方法提供给调用者

  spring中bean的创建实际就是两种:单例模式和原型模式。(当然原型模式需要和工厂模式搭配起来)

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值