设计模式以及设计模式之创建型模式(3种)

目录

什么是设计模式?

设计模式的作用?

     创建型模式(Creational Pattern)(6种)

       1、原型模式(Prototype)

        2、单例模式(Singleton)

        3、工厂模式


什么是设计模式?

设计模式(英语 design pattern)是对面向对象设计中反复出现的问题的解决方案

设计模式的作用?

(1)设计模式以一种标准的方式供广大开发人员使用,为开发者的沟通提供了一套机制,帮助开发者更好地明白和更清晰地描述一段被给出的代码。

(2)设计模式可以使人们更加方便简单复用成功的设计模式和结构。

(3)设计模式可以使人们深入理解面向对象的设计思想,提高软件的开发效率,节约设计成本。

     创建型模式(Creational Pattern)(6种)

        创建型模式:如何实例化对象?

  1. 单例模式  Singleton Pattern:保证一个类只有一个实例,并提供一个访问它的全局访问点 
  2. 简单工厂模式    Simple Factory Pattern
  3. 工厂方法模式     Factory Method Pattern:定义一个用于创建对象的接口,让子类决定实例化哪一个类,Factory Method使一个类的实例化延迟到了子类。 
  4. 抽象工厂模式     Abstract  Factory Pattern:提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们的具体类。 
  5. 原型模式  Prototype Pattern:用原型实例指定创建对象的种类,并且通过拷贝这些原型来创建新的对象。 
  6. 建造者模式  Builder Pattern:将一个复杂对象的构建与他的表示相分离,使得同样的构建过程可以创建不同的表示。 

      举例:我们举示例让我们更好的理解创建型模式?

       1、原型模式(Prototype)

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

   切入点

 1.实际项目功能开发,如何设计(课表需求)?
假如我们现在有一个需求:一眼看出周一到周日,上午下午晚上,哪些教员休息,哪些教室时空闲的?

按照这个需求来我们需要设置多少个变量?

最原始的设计:一天,三个时间段,上,下午,晚上,一周七天,这3*7=21个时间段中有两个变量,教员和教师,所以最原始的设计是有21*2=42个变量

从中我们可以发现,这种设计模式非常的笨重,不灵活,不便于维护(代码量巨大,当我们要增加或者减少一个字段时,会显得非常麻烦),这个时候,我们可以采用我们的设计模式(要按照功能,需求选择合适的设计模式)

将公共部分作为原型,通过拷贝这个原型来创建新的对象这就是原型模式

 2.开发中的陷阱(HashMap)

原型模式java代码

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);
    }
}

该方法中的hm1和hm2输出是一样的

 会输出上图结果的原因是:HashMap hm2 = hm1这一步把hm1的地址赋给hm2所以他们操作的是同一个对象,输出的也是同一个对象。

 相反,如果想得到两个不同的对象,就会采用到我们的原型设计模式,将公共部分hm1克隆一份,再对其进行操作,这时,我们得到的就是两个地址不同的集合

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);
    }

案例2

​ 需求:将一只名字为杰克、性别为母的绵羊克隆10份;

​ 要求每只绵羊的属性、性别都一致;

未使用原型模式时

package com.javaxl.design.prototype.before;
 
/**
 * @author 周大福ye
 * @site www.javaxl.com
 * @company
 * @create  2020-02-22 10:45
 */
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;
 
/**
 * @author 周大福ye
 * @site www.javaxl.com
 * @company
 * @create  2020-02-22 10:46
 *
 * 将一只名字为杰克、性别为母的绵羊克隆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;
 
/**
 * @author 周大福ye
 * @site www.javaxl.com
 * @company
 * @create  2020-02-22 10:45
 *
 * 使用原型设计模式进行设计
 */
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;
 
/**
 * @author 周大福ye
 * @site www.javaxl.com
 * @company
 * @create  2020-02-22 10:46
 *
 * 将一只名字为杰克、性别为母的绵羊克隆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;

/**
 * @author 周大福ye
 * @site www.javaxl.com
 * @company
 * @create  2020-02-22 10:45
 *
 * 使用原型设计模式进行设计
 */
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;
    }
}

方式一:(实体类不用实现序列化接口)

  @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());
 
    }

输出结果:

 第二种方式:(实现序列化接口)

  @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、实现深克隆的时候可能需要比较复杂的代码

  • ​ 应用

树形节点的拖拽删除;

应用场景

  • 单例模式的弊端

vue实现教务排课功能

  • 原型模式的应用

vue实现教务排课解决单例带来的问题

2、单例模式(Singleton)


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

应用场景:

案例

这里以经典的数据库驱动连接工具类为例;

数据库连接工具类在各个业务的dao层会被初始化调用;

而每一次初始化都会在堆内存中申请一片空间,这是对堆内存资源的浪费;

如果在堆内存只开辟一片空间,各个业务的Dao层建立不同的引用进行操作,就可以资源利用最大化;

单例设计模式就应运而生,它就是为了解决对象初始化,造成资源浪费的情况;

 多例:

 单例:

分类

饿汉式(静态常量)

饿汉式(静态代码块)

懒汉式(线程不安全)

懒汉式(线程安全,同步代码块)

懒汉式(线程安全,同步方法)

双重检查

静态内部类

枚举

package com.javaxl.design.single.after;
 
/**
 * @author 周大福ye
 * @site www.javaxl.com
 * @company
 * @create  2020-02-21 17:09
 * 饿汉式(静态常量)
 */
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

           

优缺点:

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

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

应用

jdk源码中Runtime类

tomcat中ApplicationContext类

session 工厂

Spring单例多例模式的演示、区别及选择

package com.zking.single.demo;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.zking.ioc.web.ParamAction;

/**
 * Spring单例多例模式的演示、区别及选择
 * 
 * @author 周大福ye
 *
 */
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();
	}
}

3、工厂模式

工厂模式是我们最常用的实例化对象模式了,是用工厂方法代替new操作的一种模式。

意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。

主要解决:主要解决接口选择的问题。

何时使用:我们明确地计划不同条件下创建不同实例时。

如何解决:让其子类实现工厂接口,返回的也是一个抽象的产品。

关键代码:创建过程在其子类执行。

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

结论:什么时候有值,取决于bean的存在方式:

单例:容器中的对象就默认初始化了

多例:使用该对象的时候就初始化了

工厂模式为什么要替代new的方式初始化对象?

目的在于实例化与初始化数据数据的解耦

  • 术语

    • Model 模型

    • Factory 模型工厂

  • 案例三:

    ​ 需求:一个披萨制作的项目,要求该项目易于扩展维护;

    ​ 1、能够生产出美式披萨、中式披萨...

    ​ 2、披萨制作过程包含原材料准备、烘培、切割、打包

    ​ 3、可生成披萨订单

常规模式未使用工厂模式示例代码

package com.javaxl.design.factory;

/**
 * @author 周大福ye
 * @site www.javaxl.com
 * @company
 * @create  2020-02-21 21:29
 */
public interface Pizza {
    void pre();

    void bake();

    void cut();

    void box();
}

/**
 * 中式披萨
 */
class ChinesePizza implements Pizza {

    public ChinesePizza() {
        this.pre();
        this.bake();
        this.cut();
        this.box();
    }

    @Override
    public void pre() {
        System.out.println("中式披萨材料准备...");
    }

    @Override
    public void bake() {
        System.out.println("中式披萨烘培...");
    }

    @Override
    public void cut() {
        System.out.println("中式披萨的切片...");
    }

    @Override
    public void box() {
        System.out.println("中式披萨包装盒包装");
    }
}

/**
 * 美式披萨
 */
class AmericaPizza implements Pizza {
    public AmericaPizza() {
        this.pre();
        this.bake();
        this.cut();
        this.box();
    }

    @Override
    public void pre() {
        System.out.println("美式 披萨材料准备...");
    }

    @Override
    public void bake() {
        System.out.println("美式 披萨烘培...");
    }

    @Override
    public void cut() {
        System.out.println("美式 披萨的切片...");
    }

    @Override
    public void box() {
        System.out.println("美式 披萨包装盒包装");
    }
}

class JapanPizza implements Pizza {
    public JapanPizza() {
        this.pre();
        this.bake();
        this.cut();
        this.box();
    }

    @Override
    public void pre() {
        System.out.println("日式 披萨材料准备...");
    }

    @Override
    public void bake() {
        System.out.println("日式 披萨烘培...");
    }

    @Override
    public void cut() {
        System.out.println("日式 披萨的切片...");
    }

    @Override
    public void box() {
        System.out.println("日式 披萨包装盒包装");
    }
}


public class PizzaFactory {
    public static Pizza createPizza(int no){
        switch (no){
            case 1:
                return new ChinesePizza();
            case 2:
                return new AmericaPizza();
            case 3:
                return new JapanPizza();
        }
        return null;
    }
}


public class Client {
    public static void main(String[] args) {
        Pizza chinaPizza = PizzaFactory.createPizza(1);

        System.out.println("=============================");
        Pizza americaPizza = PizzaFactory.createPizza(2);

        System.out.println("=============================");
        Pizza japanPizza = PizzaFactory.createPizza(3);
    }
}

使用工厂模式后

package com.javaxl.design.factory.after;

/**
 * @author 周大福ye
 * @site www.javaxl.com
 * @company
 * @create  2020-02-21 21:29
 */
//与未使用广场模式最大的区别
public interface Pizza {
    void pre();

    void bake();

    void cut();

    void box();
}

/**
 * 中式披萨
 */
class ChinesePizza implements Pizza {

    @Override
    public void pre() {
        System.out.println("中式披萨材料准备...");
    }

    @Override
    public void bake() {
        System.out.println("中式披萨烘培...");
    }

    @Override
    public void cut() {
        System.out.println("中式披萨的切片...");
    }

    @Override
    public void box() {
        System.out.println("中式披萨包装盒包装");
    }
}

/**
 * 美式披萨
 */
class AmericaPizza implements Pizza {

    @Override
    public void pre() {
        System.out.println("美式 披萨材料准备...");
    }

    @Override
    public void bake() {
        System.out.println("美式 披萨烘培...");
    }

    @Override
    public void cut() {
        System.out.println("美式 披萨的切片...");
    }

    @Override
    public void box() {
        System.out.println("美式 披萨包装盒包装");
    }
}

class JapanPizza implements Pizza {

    @Override
    public void pre() {
        System.out.println("日式 披萨材料准备...");
    }

    @Override
    public void bake() {
        System.out.println("日式 披萨烘培...");
    }

    @Override
    public void cut() {
        System.out.println("日式 披萨的切片...");
    }

    @Override
    public void box() {
        System.out.println("日式 披萨包装盒包装");
    }
}



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 {
        //工厂方式与new方式的根本区别
            if(no=4){
            pizza.cut();
            pizza.box();
        }else{
             pizza.pre();
            pizza.bake();
            pizza.cut();
            pizza.box();
        }
        }
        return pizza;
    }
}


public class Client {
    public static void main(String[] args) {
        Pizza chinaPizza = PizzaFactory.createPizza(1);

        System.out.println("=============================");
        Pizza americaPizza = PizzaFactory.createPizza(2);

        System.out.println("=============================");
        Pizza japanPizza = PizzaFactory.createPizza(3);

        System.out.println("=============================");
        Pizza otherPizza = PizzaFactory.createPizza(4);
    }
}

区别:对象实例化和数据初始化没有放在一起。

使用前后代码对比:

前者将对象初始化的工作交给了对象的构造函数完成;

后者将初始化的过程交给了工厂类完成;

注意事项及细节

将对象的初始化交给工厂类构造函数初始化会影响到子类,耦合度过高

应用

简单工厂:

  1. xml建模
  2. jdk源码中
  3. Calendar类

抽象工厂:

  1. Hibernate框架
  2. Spring框架
  3. Mybatis框架
  4. Shiro框架

应用场景

Bean的生命周期(单例多例bean初始化源码剖析)

package com.zking.single.demo;

import org.aspectj.apache.bcel.classfile.ClassParser;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;

import com.zking.ioc.web.ParamAction;

/**
 * Bean的生命周期
		单例对象
			出生:当容器创建时对象出生
			活着:只要容器还在,对象一直活着
			死亡:容器销毁,对象消亡
			总结:单例对象的生命周期和容器相同
		多例对象
			出生:当我们使用对象时Spring框架为我们创建
			活着:对象只要是在使用过程中就一直活着
			死亡:当对象长时间不用,且没有别的对象引用时,由Java的垃圾回收器回收
 * 
 * @author 周大福ye
 *
 */
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");
        //生产bean对象
		BeanFactory beanFactory = new XmlBeanFactory(resource );
		InstanceFactory i1 = (InstanceFactory) beanFactory.getBean("instanceFactory");
	}
}

这里有一个面试题:

Bean的生命周期
        单例对象
            出生:当容器创建时对象出生
            活着:只要容器还在,对象一直活着
            死亡:容器销毁,对象消亡
            总结:单例对象的生命周期和容器相同
        多例对象
            出生:当我们使用对象时Spring框架为我们创建
            活着:对象只要是在使用过程中就一直活着
            死亡:当对象长时间不用,且没有别的对象引用时,由Java的垃圾回收器回收

在工厂类中写几个方法

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("业务方法");
	}
}

在spring-mvc中配置一个bean(单例模式)

<bean id="instanceFactory" class="com.zking.single.demo.InstanceFactory"
		init-method="init" destroy-method="destroy"></bean>

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值