什么是模式?
模式就是别人写出来的一套解决问题的方式。
单例模式:
什么是单例模式:
单例模式就是在程序的运行过程中只有一个实例的存在。
单例模式是为了解决什么问题存在的:
在程序中多次使用同一个对象且作用相同时,为了防止频繁地创建对象使得内存飙升,单例模式可以让程序仅在内存中创建一个对象,让所有需要调用的地方都共享这一单例对象。
单例模式分为两类:
1,饿汉式:在类加载时已经创建好该对象,在程序调用时直接返回该单例对象即可,即我们在编码时就已经指明了要马上创建这个对象,不需要等到被调用时再去创建。
饿汉式优点:线程安全,
饿汉式缺点:但是耗费内存(如果这个对象我们并不需要,在类加载的时候依旧会存储到内存当中)
2,懒汉式:懒汉式创建对象的方法是在程序使用对象前,先判断该对象是否已经实例化(判空),若已实例化直接返回该类对象。,否则则先执行实例化操作。
懒汉式优点:能够更好的服务,不会占用内存空间
懒汉式缺点:线程不安全。
单例模式的步骤:
饿汉式:
1,构造器私有化。(让外部不能直接创建对象)
2,在本类中创建成员变量,指向本类对象。
3,创造一个public方法,return(返回)本类对象。(注意要设置成静态的方法,因为不能new对象,只能通过类名调用。)
4,把本类中创建的对象的变量改为静态的。(静态方法只能访问静态的变量)
懒汉式:
1,构造器私有化。(让外部不能直接创建对象)
2,创建一个本类类型的变量,但是不赋值。
3,创造一个public方法,在方法中给本类类型变量赋值。(注意要设置成静态的方法,因为不能new对象,只能通过类名调用。)
4,需要在方法中判断该对象是否已经创建。
饿汉式
package singleton;
//饿汉式单例模式
public class Singleton01 {
//构造器私有化
private Singleton01(){
}
//在本类中创建一个对象
public static Singleton01 s= new Singleton01();
//提供一个public方法获取该对象。
public static Singleton01 getSingletonTest01(){
return s;
}
}
懒汉式:
package singleton;
//懒汉式单例模式,但是线程不安全。
public class Singleton02 {
private Singleton02(){}
private static Singleton02 s=null;
public static Singleton02 getSingleton02(){
if(s==null) {
s = new Singleton02();
}
return s;
}
}
解决饿汉式的线程不安全问题
如果是以下代码会出现创建多次对象的问题,不满足单例的要求。
同时开启100个线程,总会有线程在没有赋值之前进来并同时new对象。
package singleton;
public class Test02 {
public static void main(String[] args) {
for (int i=0;i<100;i++) {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
Singleton02 s = Singleton02.getSingleton02();
System.out.println(s);
}
});
t1.start();
}
}
}
添加synchronized 来实现线程安全(加锁),但是在方法上加锁,会降低效率。
package singleton;
//懒汉式单例模式,但是线程不安全。
public class Singleton02 {
private Singleton02(){}
private static Singleton02 s=null;
public synchronized static Singleton02 getSingleton02(){
if(s==null) {
s = new Singleton02();
}
return s;
}
}
效率更高,如果不是null直接没有影响了。
注意:里面要重新判断一下,要不然无法解决线程不安全的问题。
package singleton;
//懒汉式单例模式,但是线程不安全。
public class Singleton02 {
private Singleton02(){}
private static Singleton02 s=null;
public static Singleton02 getSingleton02(){
if(s==null) {
synchronized(Singleton02.class){
if (s==null) {
s = new Singleton02();
}
}
}
return s;
}
}
模板方法设计模式:
什么是模板方法设计模式?
在模板类的模板方法当中定义核心算法骨架,具体的实现步骤可以延迟到子类当中完成。
模板类通常是一个抽象类,模板类当中的模板方法定义核心算法,这个方法通常是 final的(不是必须的)
模板类当中的抽象方法就是不确定实现的方法,这个不确定怎么实现的事情交给子类去做
没有使用模板方法设计模式
package com.template1;
/**
* 存在的问题:
* 1,算法没有得到重复使用
* 2,代码没有得到复用
*/
public class Student {
/**
* 这个方法描述的是学生的一天
*/
public void day(){
//和teacher算法相同
this.qiChuang();//this可以省略
xiShu();
chiZanCan();
doSome();
chiWanFan();
suiJiao();
}
public void qiChuang(){
System.out.println("起床");
}
public void xiShu(){
System.out.println("洗漱");
}
public void chiZanCan(){
System.out.println("吃早餐");
}
public void doSome(){
System.out.println("学生上学去学习");
}
public void chiWanFan(){
System.out.println("吃晚饭");
}
public void suiJiao(){
System.out.println("睡觉休息");
}
}
package com.template1;
public class Teacher {
/**
* 这个方法描述的是老师的一天
*/
public void day(){
//和student算法相同
this.qiChuang();//this可以省略
xiShu();
chiZanCan();
doSome();
chiWanFan();
suiJiao();
}
public void qiChuang(){
System.out.println("起床");
}
public void xiShu(){
System.out.println("洗漱");
}
public void chiZanCan(){
System.out.println("吃早餐");
}
public void doSome(){
System.out.println("老师去学校教学生知识");
}
public void chiWanFan(){
System.out.println("吃晚饭");
}
public void suiJiao(){
System.out.println("睡觉休息");
}
}
使用模板方法设计模式
package com.template2;
/**
* Teacher和Student都是Person
*
* 1,Person就是模板方法设计模式当中的模板类
* 2,day()方法就是模板方法设计模式当中的模板方法。
*
*/
public abstract class Person {//模板类通常是抽象类
//模板方法
//添加了final 之后,这个方法无法被覆盖,这样核心的算法也可以得到保护(final不是必须的)
//模板方法定义核心的算法骨架,具体地实现步骤可以延迟到子类当中去实现。
//核心算发一方面是得到了保护,不能被改变。另一方面就是算法得到了重复使用
//另外代码也得到了复用,因为算法中某些步骤的代码是固定的。这些固定的代码不会随着子类的变化而变化,这一部分代码可以写到模板类中
public final void day(){
this.qiChuang();//this可以省略
xiShu();
chiZanCan();
doSome();
chiWanFan();
suiJiao();
}
//其中的某些步骤不会随着子类的变化而变化
public void qiChuang(){
System.out.println("起床");
}
public void xiShu(){
System.out.println("洗漱");
}
public void chiZanCan(){
System.out.println("吃早餐");
}
public abstract void doSome();
public void chiWanFan(){
System.out.println("吃晚饭");
}
public void suiJiao(){
System.out.println("睡觉休息");
}
}
package com.template2;
public class Student extends Person {
@Override
public void doSome() {
System.out.println("学生去学校学习");
}
}
package com.template2;
public class Teacher extends Person{
@Override
public void doSome() {
System.out.println("老师去学校教学生知识");
}
}