JAVA常见设计模式⾯试题
⼀、单例模式
java中单例模式是⼀种常见的设计模式,单例模式的写法有好⼏种,这⾥主要介绍三种:懒汉式单例、饿汉式单例、双重检查锁定
1.单例模式有以下特点:
  a、单例类只能有⼀个实例。
  b、单例类必须⾃⼰创建⾃⼰的唯⼀实例。
  c、单例类必须给所有其他对象提供这⼀实例。
2.代码特点
  a、私有静态变量
  b、私有构造⽅法
  c、公有的静态访问⽅法 
3.懒汉式
public class Singleton {
private Singleton() {}
private static Singleton single=null;
//静态⼯⼚⽅法
public static Singleton getInstance() {
if (single == null) {
single = new Singleton();
}
return single;
}
}
懒汉式⾮线程安全
4.饿汉式
//饿汉式单例类.在类初始化时,已经⾃⾏实例化
public class Singleton1 {
private Singleton1() {}
private static final Singleton1 single = new Singleton1();
//静态⼯⼚⽅法
public static Singleton1 getInstance() {
return single;
}
}
饿汉式在类创建的同时就已经创建好⼀个静态的对象供系统使⽤,以后不再改变,所以天⽣是线程安全的。
5.懒汉式和饿汉式区别
6.双重检查锁定
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
7.应⽤场景
a、需要频繁创建的⼀些类,使⽤单例可以降低系统的内存压⼒,减少 GC。
a、某类只要求⽣成⼀个对象的时候,如⼀个班中的班长等。
b、某些类创建实例时占⽤资源较多,或实例化耗时较长,且经常使⽤。
c、某类需要频繁实例化,⽽创建的对象⼜频繁被销毁的时候,如多线程的线程池、⽹络连接池等。
e、频繁访问数据库或⽂件的对象。
⼆、⼯⼚模式
⼯⼚模式是 Java 中最常⽤的设计模式之⼀,⼯⼚模式模式的写法有好⼏种,这⾥主要介绍三种:简单⼯⼚模式、⼯⼚模式、抽象⼯⼚模式1.简单⼯⼚模式
这⾥以制造coffee的例⼦开始⼯⼚模式设计之旅。
我们知道coffee只是⼀种泛举,在点购咖啡时需要指定具体的咖啡种类:美式咖啡、卡布奇诺、拿铁等等。
*
* 拿铁、美式咖啡、卡布奇诺等均为咖啡家族的⼀种产品
* 咖啡则作为⼀种抽象概念
* @author Lsj
*
*/
public abstract class Coffee {
/**
* 获取coffee名称
* @return
*/
public abstract String getName();
}
/**
* 美式咖啡
* @author Lsj
*
*/
public class Americano extends Coffee {
@Override
public String getName() {
return "美式咖啡";
单例模式的几种实现方式
}
}
/**
* 卡布奇诺
* @author Lsj
*
*/
public class Cappuccino extends Coffee {
@Override
public String getName() {
return "卡布奇诺";
}
}
/**
* 拿铁
* @author Lsj
*
*/
public class Latte extends Coffee {
@Override
public String getName() {
return "拿铁";
}
}
2.⼯⼚模式
定义了⼀个创建对象的接⼝,但由⼦类决定要实例化的类是哪⼀个,⼯⼚⽅法让类把实例化推迟到了⼦类。
* 定义⼀个抽象的咖啡⼯⼚
* @author Lsj
*/
public abstract class CoffeeFactory {
/**
* ⽣产可制造的咖啡
* @return
*/
public abstract Coffee[] createCoffee();
}
/**
* 中国咖啡⼯⼚
* @author Lsj
*
*/
public class ChinaCoffeeFactory extends CoffeeFactory {
@Override
public Coffee[] createCoffee() {
/
/ TODO Auto-generated method stub
return new Coffee[]{new Cappuccino(), new Latte()};
}
}
/**
* 美国咖啡⼯⼚
* @author Lsj
*
*/
public class AmericaCoffeeFactory extends CoffeeFactory {
@Override
public Coffee[] createCoffee() {
// TODO Auto-generated method stub
return new Coffee[]{new Americano(), new Latte()};
}
}
/**
* ⼯⼚⽅法测试
* @author Lsj
*
*/
public class FactoryMethodTest {
static void print(Coffee[] c){
for (Coffee coffee : c) {
System.out.Name());
}
}
public static void main(String[] args) {
CoffeeFactory chinaCoffeeFactory = new ChinaCoffeeFactory();        Coffee[] chinaCoffees = ateCoffee();
System.out.println("中国咖啡⼯⼚可以⽣产的咖啡有:");
print(chinaCoffees);
CoffeeFactory americaCoffeeFactory = new AmericaCoffeeFactory();
Coffee[] americaCoffees = ateCoffee();
System.out.println("美国咖啡⼯⼚可以⽣产的咖啡有:");
print(americaCoffees);
}
}
3.抽象⼯⼚
提供⼀个接⼝,⽤于创建相关或依赖对象的家族,⽽不需要明确指定具体类。
在上述的场景上继续延伸:咖啡⼯⼚做⼤做强,引⼊了新的饮品种类:茶、 碳酸饮料。中国⼯⼚只能制造咖啡和茶,美国⼯⼚只能制造咖啡和碳酸饮料。
如果⽤上述⼯⼚⽅法⽅式,除去对应的产品实体类还需要新增2个抽象⼯⼚(茶制造⼯⼚、碳酸饮料制造⼯⼚),4个具体⼯⼚实现。随着产品的增多,会导致类爆炸。
所以这⾥引出⼀个概念产品家族,在此例⼦中,不同的饮品就组成我们的饮品家族, 饮品家族开始承担创建者的责任,负责制造不同的产品。
/
**
* 抽象的饮料产品家族制造⼯⼚
* @author Lsj
*
*/
public interface AbstractDrinksFactory {
/**
* 制造咖啡
* @return
*/
Coffee createCoffee();
/
**
* 制造茶
* @return
*/
Tea createTea();
/**
* 制造碳酸饮料
* @return
*/
Sodas createSodas();
}
/
**
* 中国饮品⼯⼚
* 制造咖啡与茶
* @author Lsj
*
*/
public class ChinaDrinksFactory implements AbstractDrinksFactory {
@Override
public Coffee createCoffee() {
// TODO Auto-generated method stub
return new Latte();
}
@Override
public Tea createTea() {
// TODO Auto-generated method stub
return new MilkTea();
}

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。