常用设计模式

Java 中一般认为有23种设计模式, 下面介绍几种常见的设计模式。总体来说设计模式分为三大类:

  • 创建型模式, 共5五种:工厂方法模式抽象工厂模式单例模式、建造者模式、原型模式。
  • 结构型模式,共7种:适配器模式装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
  • 行为型模式,共11种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

1.单例模式

所谓的单例设计指的是一个类只允许产生一个实例化对象。
最好理解的一种设计模式,分为懒汉式和饿汉式。

饿汉式: 构造方法私有化,外部无法产生新的实例化对象,只能通过static方法取得实例化对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Singleton {
/**
* 在类的内部可以访问私有结构,所以可以在类的内部产生实例化对象
*/
private static Singleton instance = new Singleton();
/**
* private 声明构造
*/
private Singleton() {

}
/**
* 返回对象实例
*/
public static Singleton getInstance() {
return instance;
}
}

懒汉式: 当第一次去使用Singleton对象的时候才会为其产生实例化对象的操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Singleton {
/**
* 声明变量
*/
private static volatile Singleton singleton = null;

/**
* 私有构造方法
*/
private Singleton() {

}
public static Singleton getInstance() {
// 还未实例化
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}

​ 当多个线程并发执行 getInstance() 方法时,懒汉式会存在线程安全问题,所以用到了 synchronized 来实现线程的同步,当一个线程获得锁的时候其他线程就只能在外等待其执行完毕。而饿汉式则不存在线程安全的问题。

适用场景:
单例模式只允许创建一个对象,因此节省内存,加快对象访问速度,因此对象需要被公用的场合适合使用,如多个模块使用同一个数据源连接对象等等。如:
(1) 需要频繁实例化然后销毁的对象。
(2) 创建对象时耗时过多或者耗资源过多,但又经常用到的对象。
(3) 有状态的工具类对象。
(4) 频繁访问数据库或文件的对象。
以下都是单例模式的经典使用场景:
(1) 资源共享的情况下,避免由于资源操作时导致的性能或损耗等。如上述中的日志文件,应用配置。
(2) 控制资源的情况下,方便资源之间的互相通信。如线程池等。

2.观察者模式

一个对象(subject)被其他多个对象(observer)所依赖。则当一个对象变化时,发出通知,其它依赖该对象的对象都会收到通知,并且随着变化。

3.装饰者模式

对已有的业务逻辑进一步的封装, 使其增加额外的功能, 要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例。

适用环境:

​ (1) 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。

​ (2) 处理那些可以撤消的职责。

​ (3) 当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的 子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。

4.适配器模式

适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。

使用场景:有动机地修改一个正常运行的系统的接口,这时应该考虑使用适配器模式。

注意事项:适配器不是在详细设计时添加的,而是解决正在服役的项目的问题。

5.工厂模式

5.1 简单工厂模式

简单工厂模式就是把对类的创建初始化全都交给一个工厂来执行,而用户不需要去关心创建的过程是什么样的,只用告诉工厂我想要什么就行了。而这种方法的缺点也很明显,违背了设计模式的开闭原则,因为如果你要增加工厂可以初始化的类的时候,你必须对工厂进行改建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
// 抽象产品类
abstract class Car {
public void run();

public void stop();
}

// 具体实现类
class Benz implements Car {
public void run() {
System.out.println("Benz开始启动了。。。。。");
}

public void stop() {
System.out.println("Benz停车了。。。。。");
}
}

class Ford implements Car {
public void run() {
System.out.println("Ford开始启动了。。。");
}

public void stop() {
System.out.println("Ford停车了。。。。");
}
}

// 工厂类
class Factory {
public static Car getCarInstance(String type) {
Car c = null;
if ("Benz".equals(type)) {
c = new Benz();
}
if ("Ford".equals(type)) {
c = new Ford();
}
return c;
}
}

public class Test {

public static void main(String[] args) {
Car c = Factory.getCarInstance("Benz");
if (c != null) {
c.run();
c.stop();
} else {
System.out.println("造不了这种汽车。。。");
}
}

5.2 工厂方法模式

设计一个工厂的接口,你想要什么东西,就写个类继承于这个工厂,这样就不用修改什么,直接添加就行了。就相当于,我这个工厂是用来生汽车的,而要什么品牌的汽车具体分到了每个车间,如果新多了一种品牌的汽车,直接新增一个车间就行了。那么问题又来了,如果想要生产大炮怎么办?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// 抽象产品角色
public interface Moveable {
void run();
}

// 具体产品角色
public class Plane implements Moveable {
@Override
public void run() {
System.out.println("plane....");
}
}

public class Broom implements Moveable {
@Override
public void run() {
System.out.println("broom.....");
}
}

// 抽象工厂
public abstract class VehicleFactory {
abstract Moveable create();
}

// 具体工厂
public class PlaneFactory extends VehicleFactory {
public Moveable create() {
return new Plane();
}
}

public class BroomFactory extends VehicleFactory {
public Moveable create() {
return new Broom();
}
}

// 测试类
public class Test {
public static void main(String[] args) {
VehicleFactory factory = new BroomFactory();
Moveable m = factory.create();
m.run();
}
}

5.3 抽象工厂模式

与工厂方法模式不同的是,工厂方法模式中的工厂只生产单一的产品,而抽象工厂模式中的工厂生产多个产品

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//抽象工厂类
public abstract class AbstractFactory {
public abstract Vehicle createVehicle();
public abstract Weapon createWeapon();
public abstract Food createFood();
}
//具体工厂类,其中Food,Vehicle,Weapon是抽象类,
public class DefaultFactory extends AbstractFactory{
@Override
public Food createFood() {
return new Apple();
}
@Override
public Vehicle createVehicle() {
return new Car();
}
@Override
public Weapon createWeapon() {
return new AK47();
}
}
//测试类
public class Test {
public static void main(String[] args) {
AbstractFactory f = new DefaultFactory();
Vehicle v = f.createVehicle();
v.run();
Weapon w = f.createWeapon();
w.shoot();
Food a = f.createFood();
a.printName();
}
}
请作者喝瓶肥宅快乐水