Java——设计模式(单例模式、工厂者模式)
一、设计模式
什么是设计模式?
开发人员总结的一些比较优秀的规则,提高代码的可复用,以及性能。
就比如说(博主自己设想的):在以前的时候,还没有设计模式,随着需求的增加以及业务场景的实现,会发现有一些代码实现特定的功能场景非常好,代码简洁且性能高效,于是慢慢的便沿用下来。初学可能不懂相关场景的实现,但是随着以后实现不同的需求以及碰到不同的场景,会愈来愈理解这些设计模式。就好比小时候背古诗,那时不懂什么意思,即便懂也没有体会,但是每天都背古诗记忆深刻,随着时间的流逝,未来的某一天会突然理解到这些诗词句的含义。跟这是同样的道理。有一些优秀的东西,当时不一定懂,但是先记忆,日后派上用场的时候就会感谢昨日的积累。
1、单例模式
单例模式:有且仅实例化一个类。
有且仅实例化一次:
A.私有的属性 ==>只能本类进行访问
B.私有的构造
C.公有的方法(返回这个对象)
场景:
工具类的编写、框架管理对象的原则
分类:
单例设置模式的分类:1.饿汉 2.懒汉 3.双重锁 4.内部类 5.枚举
a、饿汉模式
1、优点:没有锁机制,加载速度比较快。
2、缺点:项目运行就直接加载,可能导致项目出现卡顿,用户体验度比较差。
public class Hungry_man {
private static Hungry_man hungry_man = new Hungry_man(); // 私有静态,通过无参实例化
private Hungry_man(){ // 私有无参构造方法
}
public static Hungry_man getHungry_man() { // 定义一个公有的方法,外部调用内部封锁的对象。
return hungry_man;
}
}
看上面代码可以得知,上来就直接私有静态,且直接实例化一个对象。构造方法也是私有的。可以说内部相当封闭的了。下面定义一个公有静态的方法,通过外部调用到内部的东西。
b、饱汉模式
1.优点:懒加载,随用随加载。(用的时候才加载,用不到的时候,即便代码在,也不会使用)
2.缺点:在多线程中是不安全的。
public class DateUtils {
private static DateUtils dateUtils; // 私有静态属性
private DateUtils(){ // 私有构造方法
}
public static synchronized DateUtils getInstance(){ // 定义公开方法调用内部的私有对象。
if (dateUtils ==null){ // 如果对象还没有创建
dateUtils = new DateUtils(); // 则创建一个对象
}
return dateUtils; // 如果已经创建了,则返回已经有的对象。
}
}
}
学过前面同步锁的可以知道,这里不安全的。多线程不安全,加个同步锁就安全了。
c、双重锁模式
通过设置两个锁,来保证线程安全。但是博主听说设置一个锁就差不多了。如果确实需要线程安全,还是设置两个锁吧。
public class DateUtils {
private static DateUtils dateUtils; // 私有静态属性
private DateUtils(){ // 私有构造方法
}
public static synchronized DateUtils getInstance(){ // 第一把锁:synchronized这里锁的是 Class 对象
synchronized (DateUtils.class){ // 第二把锁。
if (dateUtils ==null){
dateUtils = new DateUtils();
}
return dateUtils;
}
}
}
d、内部类模式
public class DateUtils2 {
private DateUtils2(){ // 私有的无参构造方法
}
private static class Holder{
private static final DateUtils2 d = new DateUtils2(); // 私有静态最终,实例化一个对象
}
public static DateUtils2 getInstance(){ // 定义一个公有静态。返回值类型是本身。给外部一个接口,调用到内部的实例化对象
return Holder.d;
}
}
2、工厂者模式
顾名思义,需要什么的时候,就会拿那个东西。
a、分析
b、实现代码
工厂者模式,用到的就是前面学到的多态。
先定义一个抽象父类:
public abstract class Animal {
public abstract void eat();
}
然后定义两个子类,都继承这个父类:
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("我是猫,吃猫粮");
}
}
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("我是狗,吃狗粮");
}
}
然后定义一个工厂类,负责调用:
public class Factor {
public static Animal getAnimal(String type){
Animal animal = null;
if (type.equals("dog")){
animal = new Dog(); // 子类转父类。向上转型
}else if (type.equals("cat")){
animal = new Cat(); // 子类转父类。向上转型
}
return animal; // 返回对象
}
}
然后测试:
public class Test {
public static void main(String[] args) {
Animal animal = Factor.getAnimal("dog");
animal.eat();
Animal animal2 = Factor.getAnimal("cat");
animal2.eat();
}
}
运行结果:
这时候看代码,就能感觉到就像工厂一样,需要什么拿什么。