设计模式--创建型模式

目录

创建型模式

结构模式

行为模式

 原型模式(Prototype)

简介

术语

案例

 单例模式(Singleton)

简介

工厂模式(Factory)简介

抽象工厂


创建型模式


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

结构模式

```
六、Iterator,迭代器模式:提供一个方法顺序访问一个聚合对象的各个元素,而又不需要暴露该对象的内部表示。 
七、Observer,观察者模式:定义对象间一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知自动更新。 
八、Template Method,模板方法:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,TemplateMethod使得子类可以不改变一个算法的结构即可以重定义该算法得某些特定步骤。 
九、Command,命令模式:将一个请求封装为一个对象,从而使你可以用不同的请求对客户进行参数化,对请求排队和记录请求日志,以及支持可撤销的操作。 
十、State,状态模式:允许对象在其内部状态改变时改变他的行为。对象看起来似乎改变了他的类。 
十一、Strategy,策略模式:定义一系列的算法,把他们一个个封装起来,并使他们可以互相替换,本模式使得算法可以独立于使用它们的客户。 
十二、China of Responsibility,职责链模式:使多个对象都有机会处理请求,从而避免请求的送发者和接收者之间的耦合关系 
十三、Mediator,中介者模式:用一个中介对象封装一些列的对象交互。 
十四、Visitor,访问者模式:表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素类的前提下定义作用于这个元素的新操作。 
十五、Interpreter,解释器模式:给定一个语言,定义他的文法的一个表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。 
十六、Memento,备忘录模式:在不破坏对象的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。 
```

行为模式

```
十七、Composite,组合模式:将对象组合成树形结构以表示部分整体的关系,Composite使得用户对单个对象和组合对象的使用具有一致性。 
十八、Facade,外观模式:为子系统中的一组接口提供一致的界面,fa?ade提供了一高层接口,这个接口使得子系统更容易使用。 
十九、Proxy,代理模式:为其他对象提供一种代理以控制对这个对象的访问 
二十、Adapter,适配器模式:将一类的接口转换成客户希望的另外一个接口,Adapter模式使得原本由于接口不兼容而不能一起工作那些类可以一起工作。 
二十一、Decrator,装饰模式:动态地给一个对象增加一些额外的职责,就增加的功能来说,Decorator模式相比生成子类更加灵活。 
二十二、Bridge,桥模式:将抽象部分与它的实现部分相分离,使他们可以独立的变化。 
二十三、Flyweight,享元模式

 原型模式(Prototype)

简介

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

//    开发中的陷阱
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);
    }
}

术语

  prototype:原型

  clone:克隆

案例

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

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

 - 使用前

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 + '\'' +
                  '}';
      }
  }

  /*
   * 将一只名字为杰克、性别为母的绵羊克隆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("杰瑞", "母");
  
      }
  }


--使用后

/*
 * 
 * 使用原型设计模式进行设计
 */
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 小李飞刀
 * @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);
    }
}

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

 单例模式(Singleton)

简介

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

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

切入点

```
1.Spring为何默认javabean是单例的?
2.Spring为何提供javabean多例选项?
```
- 分类
  - 饿汉式(静态常量)
  - 饿汉式(静态代码块)
  - 懒汉式(线程不安全)
  - 懒汉式(线程安全,同步代码块)
  - 懒汉式(线程安全,同步方法)
  - 双重检查
  - 静态内部类
  - 枚举
 

/**
 * 饿汉式(静态常量)
 */
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单例多例模式的演示、区别及选择

/**
 * 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时就要多个心眼,是否可以考虑使用工厂模式,虽然这样做,可能多做一些工作,但会给你系统带来更大的可扩展性和尽量少的修改量。
https://baike.baidu.com/item/%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F/9852061?fr=aladdin

切入点

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

- 术语

  - Model    模型
  - Factory   模型工厂

使用前

  

```
package com.javaxl.design.factory;

/**
 * @author 小李飞刀
 * @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 小李飞刀
 * @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 {
            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);
    }
}

使用前后代码对比:

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

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

这么做的好处在于解耦自身对象实例化和对象初始化动作,还有一个因素在于构造函数的初始化会影响到子类;

- 注意事项及细节

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

抽象工厂

Hibernate框架
    Spring框架
    Mybatis框架
    Shiro框架
 

**Bean的生命周期(单例多例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>
```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值