设计模式(一)

                                             设计模式(创建型)

设计模式总体可分为创建型模式,结构型模式,行为型模式

创建型模式:单例模式,工厂模式,原型模式

单例模式

概念:保证一个类只有一个实例,并且提供一个访问该实例的全局访问点,既就是提供一个公共的方法,然后为之返回一个实例

优点:只生成一个实例,内存开销少,一般用于读取配置文件

实现方式:共五种,常见的有两种

常见:饿汉式:线程安全,调用效率高,但是不能延时加载

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

其他:

        双重检测锁式:由于JVM底层内部模型原因,偶尔出错,不建议使用

        静态内部类实现:线程安全,调用效率高,可进行延时加载

        枚举单例:线程安全,调用效率高,不能延时加载

 

饿汉式:

通俗来讲,特别饿,一上来就先创建,类初始化时候,立即加载这个对象,然后将构造器私用,通过公共方法返回创建好的对象

/**

 *

 * 饿汉式

 *

 */

public class Singel01 {

 

    //类初始化时候,立即加载这个对象,没有延时加载的优势,加载类时,是天然的线程安全

    private static Singel01 s = new Singel01();

   

    private Singel01(){ 

    }

    //方法没有同步,调用效率高

    public static Singel01 instance(){

        return s;

    }

}

 

懒汉式:

真正用的时候才创建,资源利用效率高,但是每次调用都同步,并发效率低

/*

 * 懒汉式

 */

public class Singel02 implements Serializable{

 

    //类初始化时候,不加载这个对象(延时加载,真正用的时候才加载)

    private static Singel02 s;

   

    private Singel02(){

       

    }

    //方法同步,调用效率低

    public static synchronized Singel02 instance(){

        if(s==null){

            s = new Singel02();

        }

        return s;

    }

   

}

 

双重检测锁实现:

这个模式将同步内容下方到内部,提高执行效率,不必每次获取对象是都进行同步,只有第一次才进行同步,创建以后就不同步,但是由于编译器优化的原因和JVM底层内部模型的原因,会出问题,不建议使用

/*

 * 双重检测锁实现

 */

public class Singel03 {

 

    private static Singel03 s = null;

   

    public static Singel03 instance(){

        if(s==null){

            Singel03 sc;

            synchronized (Singel03.class) {

                sc = s;

                if(sc==null){

                    sc = new Singel03();

                }

            }

            s = sc;

        }

        return s;

    }

   

}

 

静态内部类:

外部类没有static属性,则不会像饿汉式那样立即加载对象,只有真正调用时候,才会加载静态内部类,加载类时,线程是安全的,构造的对象是static final类型,从而保证了线程安全,兼备了并发高效调用和延迟加载的优势

/*

 * 通过静态内部类实现

 */

public class Single04 {

 

    private static class SinleInstance{

        private static final Single04 s = new Single04();

    }

   

    private Single04(){

       

    }

    public static Single04 instance(){

        return SinleInstance.s;

    }

}

 

 

枚举类:

/*

 * 枚举类实现

 */

public enum Singel05 {

 

    instance;

   

    public void instance(){

       

    }

}

 

如何选用?

占用资源少,不需要延时加载

枚举好于饿汉式

占用资源大,需要延时加载

静态内部类好于懒汉式

在以上5中实现单例模式中,除了枚举类,其他四种都可以通过反射和反序列化进行破解,但是枚举不行,枚举是真正意义上的天然线程安全

反射破解懒汉式:

//通过反射来实现破解,调用私有的构造器

        Class clazz = Class.forName("com.sxt.first.Singel02");

        Constructor<Singel02> c = clazz.getDeclaredConstructor(null);

        c.setAccessible(true);

        Singel02 s3 = c.newInstance();

        Singel02 s4 = c.newInstance();

        System.out.println(s3);

        System.out.println(s4);

防止反射破解:

/*

     * 抛出异常阻止反射

     */

    private Singel02(){

        if(s!=null){

            throw new RuntimeException();

        }

    }

通过反序列化漏洞实现破解

//通过反序列化的方式构造多个对象

        FileOutputStream fos = new FileOutputStream("d:/a.txt");

        ObjectOutputStream oos = new ObjectOutputStream(fos);

        oos.writeObject(s1);

        oos.close();

        fos.close();

       

        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("d:/a.txt"));

        Singel02 s6 = (Singel02) ois.readObject();

        System.out.println(s6);

防止反序列化破解

//反序列化时候,如果定义了readResolve(),则直接返回此方法指定的对象

    private Object readResolve(){

        return s;

    }

 

                                                              原型模式

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

实现方式就是对象内存的复制,内存的复制及其麻烦,但是在java中提供了对象的clone方法,使得变为简单

一某个对象为原型,复制出新的对象,新的对象具有圆形的特点

优势有:效率高,避免了执行构造方法的过程

实现:类实现Cloneable接口和clone方法

使用场景:通过new产生一个对象需要繁琐的数据准备,则可以使用原型模式

/*

 * 原型模式

 */

public class Sheep implements Cloneable,Serializable{

 

    private String name;

    private String birthday;

   

    @Override

    protected Object clone() throws CloneNotSupportedException {

        Object obj = super.clone();//直接调用Object对象的clone方法

        return obj;

    }

 

    public String getName() {

        return name;

    }

 

    public void setName(String name) {

        this.name = name;

    }

 

    public String getBirthday() {

        return birthday;

    }

 

    public void setBirthday(String birthday) {

        this.birthday = birthday;

    }

 

    public Sheep(String name, String birthday) {

        this.name = name;

        this.birthday = birthday;

    }

 

    public Sheep() {

    }

 

}

 

 

 

public class test {

         public static void main(String[] args) throws CloneNotSupportedException, Exception {

                  

                   Sheep sheep1 = new Sheep("多利","1955-03-06");

                   sheep1.setName("西安工程大学");

                   System.out.println(sheep1.getName());

                   /*Sheep sheep2 = (Sheep) sheep1.clone();

                   sheep1.setName("西安科技大学");

                   sheep2.setName("西安工程大学");

                   System.out.println(sheep1);

                   System.out.println(sheep1.getName());

                   System.out.println(sheep1.getBirthday());

                  

                   System.out.println(sheep2);

                   System.out.println(sheep2.getName());

                   System.out.println(sheep2.getBirthday());*/

                   /*

                    * 通过序列化和反序列化实现深复制

                    */

                   ByteArrayOutputStream bos = new ByteArrayOutputStream();

                   ObjectOutputStream oos = new ObjectOutputStream(bos);

                   oos.writeObject(sheep1);

                  

                   byte[] bytes = bos.toByteArray();

                   ByteArrayInputStream bis = new ByteArrayInputStream(bytes);

                   ObjectInputStream ois = new ObjectInputStream(bis);

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

                   System.out.println(sheep2.getName());

                   sheep2.setName("西安科技大学");

                   System.out.println(sheep2.getName());

                   System.out.println(sheep2.getBirthday());

                  

         }

}

测试原型模式相比传统创建对象效率

public class Sheep2 implements Cloneable{

 

    @Override

    protected Object clone() throws CloneNotSupportedException {

        Object obj = super.clone();

        return obj;

    }

    //创建对象的时候,让等待10毫秒时间

    public Sheep2(){

        try {

            Thread.sleep(10);

        } catch (InterruptedException e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        }

    }

}

 

 

/**

 * 测试效率问题

 *

 */

public class test2 {

 

    //采用new的方式创建对象

    public static void testnew(int size){

        long start = System.currentTimeMillis();

        for(int i=0;i<size;i++){

            Sheep2 s1 = new Sheep2();

        }

        long end = System.currentTimeMillis();

        System.out.println("new耗时:"+(end-start));

    }

    //采用clone方式创建对象

    public static void testclone(int size) throws Exception{

        long start = System.currentTimeMillis();

        Sheep2 s = new Sheep2();

        for(int i=0;i<size;i++){

            Sheep2 s2 = (Sheep2) s.clone();

        }

        long end = System.currentTimeMillis();

        System.out.println("clone耗时:"+(end-start));

    }

   

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

       

        test2.testnew(1000);

        test2.testclone(1000);

    }

}

 

                                                           工厂模式

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

具体可分为:简单工厂模式,工厂方法模式,抽象工厂模式

简单工厂模式:用来生产同一等级结构中的任意产品(对于新的产品,需要修改已有的代码)

工厂方法模式:用来生产同一等级结构中的固定产品(支持增加任意产品)

抽象工厂模式:用来生产不同产品族的全部产品(对于新增加的产品,无能为力,只能增加产品族)

注:工厂方法虽然满足了ocp原则,但是造成了类的增多,管理起来很不方便,因此在实际开发中,一般都采用的是简单工厂模式

代码··~~~~~~~

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值