常用的设计模式

发布于: 2020 年 06 月 24 日
常用的设计模式

今天介绍常见的设计模式,以java预言为例。分别介绍单例模式、工厂模式、适配器模式、策略模式、模板方法模式、观察者模式、组合模式和装饰器模式。

1、单例模式

顾名思义,单例模式确保一个类只有一个实例。要保证单实例,就不能让使用方调用构造方法,只能自行创建实例,并向系统提供这个实例。单例是最常见的设计模式之一,经常作为面试官手写代码的考察点。示例代码如下:

public class Singleton {
private static final Singleton instance = new Singleton();
private Singleton{}{}
public static Singleton getInstance() {
return instance;
}
}

由代码可以看出:

  • 单例类只有一个实例。

  • 单例类自己创建自己的唯一实例。

  • 单例类给提供自己创建的单一实例对象。

2、简单工厂模式

简单工厂模式又叫静态工厂方法模式。它是由一个工厂对象决定创建出那一种产品类的实例,属于类的创建者模式。类图如下:

从图中可以看出, 简单工厂模式涉及到工厂角色、抽象产品角色以及具体产品角色等三个角色。

  • 工厂类:担任这个角色的是工厂方法模式的核心,含有与应用紧密相关的商业逻辑。工厂类在客户端的直接调用下创建产品对象,它往往由一个具体的java类实现。

  • 抽象产品角色:担任这个角色的类是由工厂方法模式创建的对象的父类,或它们的共同拥有的接口。抽象产品角色可以用一个java接口或抽象类实现。

  • 具体产品角色:工厂方法模式所创建的任何对象都是这个角色的实例,具体产品角色由一个java具体类实现。

3、适配器模式

适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本接口不匹配而无法在一起工作的两个类能够在一起工作。适配器模式有两种形式,分别是类的适配器和对象的适配器。

3.1、类的适配器模式

类的适配器模式吧被适配的类的API转换成目标类的API。类图如下:

从上图中可以看出,Adaptee类并没有operation2()方法,而客户端则期待这个方法。为使客户端能够使用Adaptee类,提供一个中间环节,也就是Adapter, 把Adaptee的API与Target类的API衔接起来。Adapter与Adaptee是继承关系,这决定了这个适配器模式是类的。

3.2、对象适配器模式

与类的适配器模式一样,对象的适配器模式把被适配的类的API转换成为目标类的API,与类的适配器模式不同的是,对象适配器模式不是使用继承关系连接到Adaptee类,而是使用委派关系连接到Adaptee类。类图如下:

由图可见,Adaptee类并没有operation2()方法,而客户端期待这个方法。为使客户端能够使用Adaptee类,需要提供一个包装类Adapter,这个类包装了一个Adaptee的实例,从而此包装类能够把Adaptee的API与Target类的API衔接起来。Adapter和Adaptee是委派关系,这决定了这个适配器模式是对象的。

4、策略模式

策略模式属于对象的行为模式。其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。

这个模式设计三个角色:

  • 环境(Context)角色:持有一个Strategy类的引用。

  • 抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或者抽象类实现。此角色给出所有的具体策略类所需的接口。

  • 具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。

5、模板方法模式

模板方法模式也是类的行为模式。准备一个抽象类,将部分逻辑以具体方法及构造器的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。模板方法是最常用的设计模式之一。

模板方法模式是基于集成的代码复用的基本技术,模板方法模式的结构和用法也是面向对象设计的核心。类图如下:

  • AbstractClass定义一个或多个抽象操作,以便让子类实现。这些抽象操作叫做基本操作或基本方法,它们是一个顶级逻辑的组成步骤;定义并实现了一个模板方法,这个模板方法一般是一个具体方法,它给出了一个顶级逻辑的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类实现。

  • ConcreteClass实现了父类定义的一个或多个抽象方法。它们是一个顶级逻辑的组成步骤。每一个抽象模板都可以有多个具体模板角色,而每一个具体模板都可以给出这些抽象方法的不同实现,从而使得顶级逻辑的实现各不相同。

6、观察者模式

观察者模式是对象的行为模式。观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有的观察者对象,使它们能够自动更新自己。

从图中可以看出,观察者模式有以下角色:

  • 抽象主题(Subject)角色:抽象主题提供一个接口,用来增加和删除观察者对象。

  • 抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。

  • 具体主题(ConcreteSubject)角色:将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。

  • 具体观察者(ConcreteObserver)角色:存储与主题的状态自恰的状态。它实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。如果需要,具体观察者角色可以保持一个指向具体主题对象的引用。

示例代码:

/**
* Subject接口
*/
public interface Subject {
void attach(Observer observer);
void detach(Observer observer);
void notifyObservers();
}
/**
*ConcreteSubject类
*/
public class ConcreteSubject implements Subject{
private List<Observer> observers = new ArrayList<>();
@Override
public void attach(Observer observer) {
observers.add(observer);
}
@Override
public void detach(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer ob : Observers) {
ob.update();
}
}
}
/**
* Observer接口
*/
public interface Observer {
void update();
}
/**
*ConcreteObserver类
*/
public class ConcreteObserver implements Observer {
@Override
public void update() {
System.out.println("Hi, I am notified");
}
}

6.1、Java语音提供的对观察者模式的支持

java提供了Observable和Observer接口,以对观察者模式支持。

  • Observer接口:这个接口提供了一个方法,即update()方法。当被观察对象的状态发生变化了,被观察者对象的notifyObservers()方法就会调用这个方法。

  • Observable接口:被观察者类都是这个类的子类。Observable提供了公开的方法支持观察者对象,这些方法中有两个方法对它的子类非常重要:一个是setChanged(),另一个是notifyObservers()。

用户头像

stars

关注

架构师的肚是杂货铺 2018.02.19 加入

还未添加个人简介

评论

发布
暂无评论
常用的设计模式