设计模式5-面试

提示:本章节为《java面试系列》
类似章节:java中设计模式
设计模式2
设计模式3
设计模式4

1. 说明
本文主要介绍抽象工厂,观察者,策略,装饰。其他的模式,后面看情况再总结。

2. 介绍顺序

抽象工厂
观察者
策略
装饰

3. 正文

  • 抽象工厂
    提供一个用来创建一个产品家族的抽象类型,这个类型的子类定义了产品被生产的方法。
    当需要创建产品家族和想让制造的相关产品集合起来时,就可以使用该模式。

类图+解释:

抽象工厂模式创建很多对象的而不是一个对象,并且这些对象是相关的,也就是说必须一起创建出来。而工厂方法模式只是用于创建一个对象,这和抽象工厂模式有很大不同。

抽象工厂模式用到了工厂方法模式来创建单一对象,AbstractFactory 中的 createProductA() 和 createProductB() 方法都是让子类来实现,这两个方法单独来看就是在创建一个对象,这符合工厂方法模式的定义。

至于创建对象的家族这一概念是在 Client 体现,Client 要通过 AbstractFactory 同时调用两个方法来创建出两个对象,在这里这两个对象就有很大的相关性,Client 需要同时创建出这两个对象。

从高层次来看,抽象工厂使用了组合,即 Cilent 组合了 AbstractFactory,而工厂方法模式使用了继承。如下图:
在这里插入图片描述
代码实现:

class AbstractProductA {
}
class AbstractProductB{
}

class ProductA1 extends AbstractProductA {
}

class ProductA2 extends AbstractProductA {
}

class ProductB1 extends AbstractProductB{
}

class ProductB2 extends AbstractProductB{
}

abstract class AbstractFactory {
    abstract AbstractProductA createProductA();
    abstract AbstractProductB createProductB();
}

class ConcreateFactory1 extends AbstractFactory{
    @Override
    AbstractProductA createProductA() {
        return new ProductA1();
    }

    @Override
    AbstractProductB createProductB() {
        return new ProductB1();
    }
}

class ConcreateFactory2 extends AbstractFactory{
    @Override
    AbstractProductA createProductA() {
        return new ProductA2();
    }

    @Override
    AbstractProductB createProductB() {
        return new ProductB2();
    }
}

public class Client {
    public static void main(String[] args) {
        AbstractFactory abstractFactory =new ConcreateFactory1();
        AbstractProductA productA = abstractFactory.createProductA();
        AbstractProductB productB = abstractFactory.createProductB();

    }
}
  • 观察者模式

定义对象之间的一对多依赖,当一个对象状态改变时,它的所有依赖都会收到通知并且自动更新状态。

主题(Subject)是被观察的对象,而其所有依赖者(Observer)称为观察者。如下图所示:(出版者+订阅者=观察者模式)
在这里插入图片描述
类图+解释:
主题(Subject)具有注册和移除观察者、并通知所有观察者的功能,主题是通过维护一张观察者列表来实现这些操作的。

观察者(Observer)的注册功能需要调用主题的 registerObserver() 方法。如下图:
在这里插入图片描述

代码实现:
天气数据布告板会在天气信息发生改变时更新其内容,布告板有多个,并且在将来会继续增加。如下图:(图只画出其中一个)
在这里插入图片描述

import java.util.ArrayList;
import java.util.List;

interface Subject {
    void registerObserver(Observer o);

    void removeObserver(Observer o);

    void notifyObserver();
}

class WeatherData implements Subject {
    private List<Observer> observers;
    private float temperature;
    private float humidity;
    private float pressure;

    public WeatherData() {
        observers = new ArrayList<>();
    }

    public void setMeasurements(float temperature, float humidity, float pressure) {
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        notifyObserver();
    }

    @Override
    public void registerObserver(Observer o) {
        observers.add(o);
    }

    @Override
    public void removeObserver(Observer o) {
        int i = observers.indexOf(o);
        if (i >= 0) {
            observers.remove(i);
        }
    }

    @Override
    public void notifyObserver() {
        for (Observer o : observers) {
            o.update(temperature, humidity, pressure);
        }
    }
}

interface Observer {
    void update(float temp, float humidity, float pressure);
}

 class StatisticsDisplay implements Observer {

    public StatisticsDisplay(Subject weatherData) {
        weatherData.registerObserver(this);
    }

    @Override
    public void update(float temp, float humidity, float pressure) {
        System.out.println("StatisticsDisplay.update: " + temp + " " + humidity + " " + pressure);
    }
}

class CurrentConditionsDisplay implements Observer {

    public CurrentConditionsDisplay(Subject weatherData) {
        weatherData.registerObserver(this);
    }

    @Override
    public void update(float temp, float humidity, float pressure) {
        System.out.println("CurrentConditionsDisplay.update: " + temp + " " + humidity + " " + pressure);
    }
}

public class WeatherStation {
    public static void main(String[] args) {
        WeatherData weatherData = new WeatherData();
        CurrentConditionsDisplay current = new CurrentConditionsDisplay(weatherData);
        StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData);

        weatherData.setMeasurements(30, 30, 30);
        weatherData.setMeasurements(100, 100, 100);
    }
}

输出:
在这里插入图片描述

  • 策略模式
    定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。

类图+解释:
Strategy 接口定义了一个算法族,它们都实现了 behavior() 方法。
Context 是使用到该算法族的类,其中的 doSomething() 方法会调用 behavior(),setStrategy(Strategy) 方法可以动态地改变 strategy 对象,也就是说能动态地改变 Context 所使用的算法。如下图所示:
在这里插入图片描述
与状态模式的比较:
状态模式的类图和策略模式类似,并且都是能够动态改变对象的行为。但是状态模式是通过状态转移来改变 Context 所组合的 State 对象,而策略模式是通过 Context 本身的决策来改变组合的 Strategy 对象。所谓的状态转移,是指 Context 在运行过程中由于一些条件发生改变而使得 State 对象发生改变,注意必须要是在运行过程中。

状态模式主要是用来解决状态转移的问题,当状态发生转移了,那么 Context 对象就会改变它的行为;而策略模式主要是用来封装一组可以互相替代的算法族,并且可以根据需要动态地去替换 Context 使用的算法。

代码实现:

interface QuackBehavior{
    void quack();
}

class Quack implements QuackBehavior{

    @Override
    public void quack() {
        System.out.println("呱呱呱");
    }
}

class Squeak implements QuackBehavior{

    @Override
    public void quack() {
        System.out.println("叽叽叽");
    }
}

class Duck{
    private QuackBehavior quackBehavior;

    public void performQuack(){
        if (quackBehavior != null){
            quackBehavior.quack();
        }
    }

    public void setQuackBehavior(QuackBehavior quackBehavior){
        this.quackBehavior = quackBehavior;
    }
}
public class Client2 {
    public static void main(String[] args) {
        Duck duck = new Duck();
        duck.setQuackBehavior(new Squeak());
        duck.performQuack();

        duck.setQuackBehavior(new Quack());
        duck.performQuack();
    }
}

输出:
在这里插入图片描述

  • 装饰模式
    为对象动态添加功能。
    假设咖啡店中顾客想要摩卡和奶泡深焙咖啡:
    在这里插入图片描述
    类图+解释:

装饰者(Decorator)和具体组件(ConcreteComponent)都继承自组件(Component),具体组件的方法实现不需要依赖于其它对象,而装饰者组合了一个组件,这样它可以装饰其它装饰者或者具体组件。所谓装饰,就是把这个装饰者套在被装饰者之上,从而动态扩展被装饰者的功能。装饰者的方法有一部分是自己的,这属于它的功能,然后调用被装饰者的方法实现,从而也保留了被装饰者的功能。可以看到,具体组件应当是装饰层次的最低层,因为只有具体组件的方法实现不需要依赖于其它对象。如下所示:

在这里插入图片描述
代码实现:
下图表示在 DarkRoast 饮料上新增新添加 Mocha 配料,之后又添加了 Whip 配料。DarkRoast 被 Mocha 包裹,Mocha 又被 Whip 包裹。它们都继承自相同父类,都有 cost() 方法,外层类的 cost() 方法调用了内层类的 cost() 方法。
在这里插入图片描述

interface Beverage {
    double cost();
}

class DarkRoast implements Beverage{

    @Override
    public double cost() {
        return 1;
    }
}

class HouseBlend implements Beverage{

    @Override
    public double cost() {
        return 1;
    }
}

abstract class  CondimentDecorator implements Beverage {
    protected Beverage beverage;
}

class Milk extends CondimentDecorator{

    public Milk(Beverage beverage){
        this.beverage = beverage;
    }


    @Override
    public double cost() {
        return 1 + beverage.cost();
    }
}

class Mocha extends CondimentDecorator{

    public Mocha(Beverage beverage){
        this.beverage = beverage;
    }


    @Override
    public double cost() {
        return 1+beverage.cost();
    }
}
public class Client3 {
    public static void main(String[] args) {

        Beverage beverage = new HouseBlend();
        beverage = new Mocha(beverage);
        beverage = new Milk(beverage);

        System.out.println(beverage.cost());
    }
}

小编不才,欢迎大家指出不正确的地方!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值