设计模式之创建模式

创建模式

原型模式prototype:

简介:用原型实例指定创建对象的种类,并且通过拷贝这个原型来创建新的对象。

切入点:课表排课:常规计算42个变量

弊端:代码量大,不利于维护

解决办法:设计两个变量Json.parse(json.stringfy(变量))

概念:将原型对象拷贝出新的实例,浅拷贝:只拷贝原型本身,不拷贝原型对象中的应用对象(堆内存)。深拷贝:会拷贝原型对象以及引用对象。
 

  - 使用前

  ```
  package com.javaxl.design.prototype.before;
  
 
  public class Sheep {
      private String name;
      private String sex;
  
      public Sheep(String name, String sex) {
          this.name = name;
          this.sex = sex;
      }
  
      public String getName() {
          return name;
      }
  
      public void setName(String name) {
          this.name = name;
      }
  
      public String getSex() {
          return sex;
      }
  
      public void setSex(String sex) {
          this.sex = sex;
      }
  
      @Override
      public String toString() {
          return "Sheep{" +
                  "name='" + name + '\'' +
                  ", sex='" + sex + '\'' +
                  '}';
      }
  }
  
  
  package com.javaxl.design.prototype.before;
  
  /**
  
   *
   * 将一只名字为杰克、性别为母的绵羊克隆10份;
   * ​    要求每只绵羊的属性、性别都一致;
   *
   * 弊端:无法将当前的状态进行复制
   */
  public class Client {
      public static void main(String[] args) {
          Sheep sheep1 = new Sheep("杰西", "母");
          Sheep sheep2 = new Sheep("杰西", "母");
          Sheep sheep3 = new Sheep("杰西", "母");
          Sheep sheep4 = new Sheep("杰西", "母");
          Sheep sheep5 = new Sheep("杰西", "母");
          Sheep sheep6 = new Sheep("杰西", "母");
          Sheep sheep7 = new Sheep("杰西", "母");
          Sheep sheep8 = new Sheep("杰西", "母");
          Sheep sheep9 = new Sheep("杰西", "母");
          Sheep sheep10 = new Sheep("杰西", "母");
  
  //        此时我要一只名为杰瑞的绵羊,其它绵羊属性与杰西一致;
  //        那么按照这种设计,只能这么创建所需的绵羊
  //        这种方式创建,目前只有两个属性问题不大,如果绵羊类有十几二十甚至更多的属性,那么是非常不方便的
          Sheep sheep11 = new Sheep("杰瑞", "母");
  
      }
  }
  

  

  

  - 使用后

```
package com.javaxl.design.prototype.after;

/**
 * 使用原型设计模式进行设计
 */
public class Sheep implements Cloneable{
    private String name;
    private String sex;

    public Sheep(String name, String sex) {
        this.name = name;
        this.sex = sex;
    }

    public String getName() {
        return name;
    }

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

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

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

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Object obj =  super.clone();
        System.out.println("被克隆了...");
        return obj;
    }
}


package com.javaxl.design.prototype.after;

/**
 * 将一只名字为杰克、性别为母的绵羊克隆10份;
 * ​    要求每只绵羊的属性、性别都一致;
 *
 *   使用原型设计模式进行设计后的测试
 */
public class Client {
    public static void main(String[] args) throws Exception{
        Sheep sheep1 = new Sheep("杰西", "母");
        Sheep sheep2 = (Sheep) sheep1.clone();
        Sheep sheep3 = (Sheep) sheep1.clone();
        Sheep sheep4 = (Sheep) sheep1.clone();
        Sheep sheep5 = (Sheep) sheep1.clone();
        Sheep sheep6 = (Sheep) sheep1.clone();
        Sheep sheep7 = (Sheep) sheep1.clone();
        Sheep sheep8 = (Sheep) sheep1.clone();
        Sheep sheep9 = (Sheep) sheep1.clone();
        Sheep sheep10 = (Sheep) sheep1.clone();
        System.out.println(sheep1);
        System.out.println(sheep2);

//        此时我要一只名为杰瑞的绵羊,其它绵羊属性与杰西一致;
//        按照原型设计模式,调用方Client类无需查找杰西相同部分的属性,只需变动差异部分属性进行克隆即可;
//        这种设计,目前只有两个属性使用起来感觉没多大区别,如果绵羊类有十几二十甚至更多的属性,那么感觉非常明显
        sheep1.setName("杰瑞");//其它的属性不需要去关注
        Sheep sheep11 = (Sheep) sheep1.clone();
        System.out.println(sheep11);
    }
}

浅拷贝:


  package com.javaxl.design.prototype.light;
  
  /**
   * 使用原型设计模式进行设计
   */
  public class Sheep implements Cloneable{
      private String name;
      private String sex;
      private Sheep friend;
  
      public Sheep(String name, String sex) {
          this.name = name;
          this.sex = sex;
      }
  
      public String getName() {
          return name;
      }
  
      public void setName(String name) {
          this.name = name;
      }
  
      public String getSex() {
          return sex;
      }
  
      public void setSex(String sex) {
          this.sex = sex;
      }
  
      public Sheep getFriend() {
          return friend;
      }
  
      public void setFriend(Sheep friend) {
          this.friend = friend;
      }
  
      @Override
      public String toString() {
          return "Sheep{" +
                  "name='" + name + '\'' +
                  ", sex='" + sex + '\'' +
                  ", friend=" + friend +
                  '}';
      }
  
      @Override
      protected Object clone() throws CloneNotSupportedException {
          Object obj =  super.clone();
          System.out.println("被克隆了...");
          return obj;
      }
  }
  
  ```

深拷贝:

   - 方式一

    ```
    package com.javaxl.design.prototype.deep.one;
    
    /**
     * 使用原型设计模式进行设计
     */
    public class Sheep implements Cloneable {
        private String name;
        private String sex;
        private Sheep friend;
        private Sheep boyFriend;
    
        public Sheep(String name, String sex) {
            this.name = name;
            this.sex = sex;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getSex() {
            return sex;
        }
    
        public void setSex(String sex) {
            this.sex = sex;
        }
    
        public Sheep getFriend() {
            return friend;
        }
    
        public void setFriend(Sheep friend) {
            this.friend = friend;
        }
    
        public Sheep getBoyFriend() {
            return boyFriend;
        }
    
        public void setBoyFriend(Sheep boyFriend) {
            this.boyFriend = boyFriend;
        }
    
        @Override
        public String toString() {
            return "Sheep{" +
                    "name='" + name + '\'' +
                    ", sex='" + sex + '\'' +
                    ", friend=" + friend +
                    '}';
        }
    
        @Override
        protected Object clone() throws CloneNotSupportedException {
            Object obj = super.clone();
            if (obj == null) {
                return obj;
            } else {
                //        被克隆出来的绵羊(目前这只绵羊的朋友还是本体的朋友)
                Sheep sheep = (Sheep) obj;
    //        将本体的朋友也克隆一份出来,给克隆羊
                Sheep friend = this.getFriend();
                if (friend !=null){
                    sheep.setFriend((Sheep) friend.clone());
                }
                return sheep;
            }
        }
    }
    
    
    package com.javaxl.design.prototype.deep.one;
    
    /**
     * 将一只名字为杰克、性别为母的绵羊克隆10份;
     * ​	要求每只绵羊的属性、性别都一致;
     * <p>
     * 使用原型设计模式进行设计后的测试
     */
    public class Client {
        public static void main(String[] args) throws Exception {
            Sheep sheep1 = new Sheep("杰西", "母");
            Sheep friend_jiexi = new Sheep("杰西的朋友", "公");
            Sheep boyFriend_jiexi = new Sheep("杰西的男朋友", "公");
            sheep1.setFriend(friend_jiexi);
            sheep1.setBoyFriend(boyFriend_jiexi);
            Sheep sheep2 = (Sheep) sheep1.clone();
    
    
            System.out.println("第1只叫杰西的绵羊的朋友:" + sheep1.getFriend().hashCode());
            System.out.println("第2只叫杰西的绵羊的朋友:" + sheep2.getFriend().hashCode());
    
            System.out.println("第1只叫杰西的绵羊的男朋友:" + sheep1.getBoyFriend().hashCode());
            System.out.println("第2只叫杰西的绵羊的男朋友:" + sheep2.getBoyFriend().hashCode());
    
        }
    }
    
    
    ```

    

    ![](创建型模式.assets/1582343860268-1582641669694.png)

    

    

    - 方式二

  ```
  package com.javaxl.design.prototype.deep.two;
  
  import java.io.*;
  
  /**
   * 使用原型设计模式进行设计
   */
  public class Sheep implements Cloneable,Serializable{
      private String name;
      private String sex;
      private Sheep friend;
      private Sheep boyFriend;
  
      public Sheep getBoyFriend() {
          return boyFriend;
      }
  
      public void setBoyFriend(Sheep boyFriend) {
          this.boyFriend = boyFriend;
      }
  
      public Sheep(String name, String sex) {
          this.name = name;
          this.sex = sex;
      }
  
      public String getName() {
          return name;
      }
  
      public void setName(String name) {
          this.name = name;
      }
  
      public String getSex() {
          return sex;
      }
  
      public void setSex(String sex) {
          this.sex = sex;
      }
  
      public Sheep getFriend() {
          return friend;
      }
  
      public void setFriend(Sheep friend) {
          this.friend = friend;
      }
  
      @Override
      public String toString() {
          return "Sheep{" +
                  "name='" + name + '\'' +
                  ", sex='" + sex + '\'' +
                  ", friend=" + friend +
                  '}';
      }
  
      @Override
      protected Object clone() throws CloneNotSupportedException {
          Object obj =  super.clone();
          System.out.println("被克隆了...");
          return obj;
      }
  
      protected Object deepClone() throws CloneNotSupportedException, IOException, ClassNotFoundException {
  //        序列化
          ByteArrayOutputStream bos = new ByteArrayOutputStream();
  //        获取对象输出流
          ObjectOutputStream oos = new ObjectOutputStream(bos);
  //        将当前的对象
          oos.writeObject(this);
  
  //        反序列化
          ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
          Object obj = ois.readObject();
          return obj;
      }
  }
  
  
  public class Client {
      public static void main(String[] args) throws Exception {
          Sheep sheep1 = new Sheep("杰西", "母");
          Sheep friend_jiexi = new Sheep("杰西的朋友", "公");
          Sheep boyFriend_jiexi = new Sheep("杰西的男朋友", "公");
          sheep1.setFriend(friend_jiexi);
          sheep1.setBoyFriend(boyFriend_jiexi);
          Sheep sheep2 = (Sheep) sheep1.deepClone();
  
          System.out.println("第1只叫杰西的绵羊的朋友:" + sheep1.getFriend().hashCode());
          System.out.println("第2只叫杰西的绵羊的朋友:" + sheep2.getFriend().hashCode());
  
          System.out.println("第1只叫杰西的绵羊的男朋友:" + sheep1.getBoyFriend().hashCode());
          System.out.println("第2只叫杰西的绵羊的男朋友:" + sheep2.getBoyFriend().hashCode());
  
      }
  }
  
  ```

注意事项和细节
  - 创建新的对象比较复杂时,可以利用原型模式简化对象的创建过程,同时也能够提高效率
  - 不用重新初始化对象,而是动态地获得对象运行时的状态
  - 如果原始对象发生变化(增加或者减少属性),其它克隆对象的也会发生相应的变化,无需修改代码

​缺点:
​        1、需要为每一个类配备一个克隆方法,这对全新的类来说不是很难,但对已有的类进行改造时,需要修改其源代码,违背了 ocp 原则
​        2、实现深克隆的时候可能需要比较复杂的代码
 

结论:从对象创建的角度上来说,原型模式设计让相似的类实例创建更加的便捷

单例模式singlon:

简介:保证一个类只有一个实例,并提供一个访问它的全局访问点

切入点:Spring中bean对象是单例的?

优点:极大的节约了Jvm的内存空间

缺点:会存在变量污染问题;


public class Demo1 {
//    public static void main(String[] args) {
//        HashMap hm1 = new HashMap();
//        hm1.put("name","zs");
//        hm1.put("sex","女");
//        HashMap hm2 = hm1;
//        hm1.put("age","18");
//        hm2.put("like","男");
//        System.out.println(hm1);
//        System.out.println(hm2);
//    }

    public static void main(String[] args) {
        HashMap hm1 = new HashMap();
        hm1.put("name","zs");
        hm1.put("sex","女");
        HashMap hm2 = (HashMap) hm1.clone();
        hm1.put("age","18");
        hm2.put("like","男");
        System.out.println(hm1);
        System.out.println(hm2);
    }
}

综上:Spring就是提供多例配置socpe="prototype"

体现形式:

  1.  饿汉式(静态常量) final static Dbaccess dbaccess=new Dbaccess();
  2.  饿汉式(静态代码块)static{}
  3. 懒汉式(线程不安全) if()
  4. 懒汉式(线程安全,同步代码块) synchronized
  5. 懒汉式(线程安全,同步方法)
  6. 双重检查
  7. 静态内部类
  8. 枚举
    
    
    /**
     * 饿汉式(静态常量)
     */
    public class DBAccess {
        //    构造器私有化,避免外部创建对象
        private DBAccess() {
    
        }
    
        //    static修饰,保障其能够被静态方法访问
        private final static DBAccess dbAccess = new DBAccess();
    
        //    外部直接调用静态方法实例化对象
        public static DBAccess getInstance() {
            return dbAccess;
        }
    
    }
    
    /**
     * 饿汉式(静态代码块)
     */
    class DBAccess2 {
        private DBAccess2() {
    
        }
    
        private static DBAccess2 dbAccess = null;
    
        static {
            dbAccess = new DBAccess2();
        }
    
        public static DBAccess2 getInstance() {
            return dbAccess;
        }
    }
    
    /**
     * 懒汉式(线程不安全)
     */
    class DBAccess3 {
        private DBAccess3() {
    
        }
    
        private static DBAccess3 dbAccess = null;
    
        public static DBAccess3 getInstance() {
            if (dbAccess == null) {
                dbAccess = new DBAccess3();
            }
            return dbAccess;
        }
    }
    
    /**
     * 懒汉式(同步代码块)
     */
    class DBAccess4 {
        private DBAccess4() {
    
        }
    
        private static DBAccess4 dbAccess = null;
    
        public static DBAccess4 getInstance() {
            synchronized (DBAccess4.class) {
                if (dbAccess == null) {
                    dbAccess = new DBAccess4();
                }
            }
            return dbAccess;
        }
    }
    
    /**
     * 懒汉式(线程安全,同步方法)
     */
    class DBAccess5 {
        private DBAccess5() {
    
        }
    
        private static DBAccess5 dbAccess = null;
    
        public synchronized static DBAccess5 getInstance() {
            if (dbAccess == null) {
                dbAccess = new DBAccess5();
            }
            return dbAccess;
        }
    }
    
    /**
     * 双重检查
     */
    class DBAccess6 {
        private DBAccess6() {
    
        }
    
        private static DBAccess6 dbAccess = null;
    
        public static DBAccess6 getInstance() {
            if (dbAccess == null) {
                synchronized (DBAccess6.class) {
                    if (dbAccess == null) {
                        dbAccess = new DBAccess6();
                    }
                }
            }
            return dbAccess;
    //        return new DBAccess6();
        }
    }
    
    /**
     * 静态内部类
     */
    class DBAccess7 {
        private DBAccess7() {
    
        }
    
        private static class DBAccess7Instance{
            private static DBAccess7 dbAccess = new DBAccess7();
        }
    
        public static DBAccess7 getInstance() {
            return DBAccess7Instance.dbAccess;
        }
    }
    
    /**
     * 枚举
     */
    enum DBAccess8{
        DBACCESS;
        public static DBAccess8 getInstance() {
            return DBAccess8.DBACCESS;
        }
    }
    
    
    /**
    ​ *	结论:
     *
     ​*		单例中两种饿汉式可用,但是存在性能问题
     *
    ​ *		单例中三种懒汉式不推荐,存在线程安全问题,同步方法的方式解决了线程的问题,但是性能极差
     *
    ​ *		最后三种单例模式值得推荐
     *
     *
     *
     *注意事项
     * 系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象
     * 使用单例模式可以提高系统性能
     *
     * 当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,而不是使用 new
     */
    
    

    应用:

    /**
     * Spring单例多例模式的演示、区别及选择
     * 
     * @author Administrator
     *
     */
    public class Demo1 {
    	// scope="singleton" 默认的
    	@Test
    	public void test1() {
    		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-context.xml");
    		ParamAction p1 = (ParamAction) applicationContext.getBean("paramAction");
    		ParamAction p2 = (ParamAction) applicationContext.getBean("paramAction");
    		System.out.println(p1 == p2);
    	}
    
    	// scope="prototype"
    	@Test
    	public void test2() {
    		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-context.xml");
    		ParamAction p1 = (ParamAction) applicationContext.getBean("paramAction");
    		ParamAction p2 = (ParamAction) applicationContext.getBean("paramAction");
    		System.out.println(p1 == p2);
    	}
    
    	// 区别:单例多例的选择?
    	@Test
    	public void test3() {
    		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-context.xml");
    		ParamAction p1 = (ParamAction) applicationContext.getBean("paramAction");
    		ParamAction p2 = (ParamAction) applicationContext.getBean("paramAction");
    		p1.execute();
    		p2.execute();
    	}
    }

工厂模式(Factory)

简介:是用工厂方法代替new操作的一种模式。著名的Jive论坛 ,就大量使用了工厂模式,工厂模式在Java程序系统可以说是随处可见。因为工厂模式就相当于创建实例对象的new,我们经常要根据类Class生成实例对象,如A a=new A() 工厂模式也是用来创建实例对象的,所以以后new时就要多个心眼,是否可以考虑使用工厂模式,虽然这样做,可能多做一些工作,但会给你系统带来更大的可扩展性和尽量少的修改量。

切入点:Spring中的javabean是什么时候初始化的,是容器初始化时候还是工厂创建对象初始化;

Bean生命周期:

/**
 * Bean的生命周期
		单例对象
			出生:当容器创建时对象出生
			活着:只要容器还在,对象一直活着
			死亡:容器销毁,对象消亡
			总结:单例对象的生命周期和容器相同
		多例对象
			出生:当我们使用对象时Spring框架为我们创建
			活着:对象只要是在使用过程中就一直活着
			死亡:当对象长时间不用,且没有别的对象引用时,由Java的垃圾回收器回收
 * 
 * @author Administrator
 *
 */
public class Demo2 {
	
//	单例对象与多例对象的初始化时间不一样	通过scope属性来演示
	@Test
	public void test1() {
		ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-context.xml");
	}
	
//	单例对象与多例对象的初始化时间不一样	通过scope属性来演示
	@Test
	public void test2() {
		ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-context.xml");
		InstanceFactory i1 = (InstanceFactory) applicationContext.getBean("instanceFactory");
		i1.service();
//		scope="prototype",容器关闭不会自动销毁bean对象
		applicationContext.close();
	}
	
	/**
	 * 说明了两点:
	 * scope的值对应的是两个工厂类,生产javabean的模式一样;
	 * 1.一个是单例一个是多例
	 * 2.一个是立即初始化,一个是使用初始化
	 * 反正要初始化一次,干脆把所有的初始化操作放到监听器里面去,提高系统应用的性能
	 * 多例本身会耗性能,那么就尽可能在使用的时候再去创造对象
	 */
	@Test
	public void test3() {
//		ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-context.xml");
		
		Resource resource = new ClassPathResource("/spring-context.xml");
		BeanFactory beanFactory = new XmlBeanFactory(resource );
		InstanceFactory i1 = (InstanceFactory) beanFactory.getBean("instanceFactory");
	}
}

//其他
package com.zking.single.demo;

public class InstanceFactory {
	public void init() {
		System.out.println("初始化方法");
	}
	
	public void destroy() {
		System.out.println("销毁方法");
	}
	
	public void service() {
		System.out.println("业务方法");
	}
}

<bean id="instanceFactory" class="com.zking.single.demo.InstanceFactory"
		scope="prototype" init-method="init" destroy-method="destroy"></bean>
//应用:将初始化放到工厂类,优化代码
public class PizzaFactory {
    public static Pizza createPizza(int no){
        Pizza pizza = null;
        switch (no){
            case 1:
                pizza = new ChinesePizza();
                break;
            case 2:
                pizza = new AmericaPizza();
                break;
            case 3:
                pizza = new JapanPizza();
                break;
        }
        if (pizza == null){
            System.out.println("没有此披萨订购服务");
        }else {
            pizza.pre();
            pizza.bake();
            pizza.cut();
            pizza.box();
        }
        return pizza;
    }
}

  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值