【设计模式】通过在苹果官网购买iPhone配件了解装饰器模式
创始人
2025-06-30 02:20:58
0

背景

一个iPhone,可以套上保护壳(ConcDecorator A),也可以再套上无线充(ConcDecorator B),得到最后的效果(execute)。

苹果无需发布新的型号(继承),我们简单地通过装饰(组合)就可以得到想要的最终产品。

模式定义

Attach additional responsibilities to an object dynamically keeping the same interface. Decorators provide a flexible alternative to subclassing for extending functionality.

为动态保持相同接口的对象附加额外的职责。装饰器为扩展功能提供了一种灵活的选择,而不是子类化。

可以看到,是十分符合我们的需求的,每一个装饰品如保护壳、无线充,就是一个个可以嵌套的装饰器。

https://refactoringguru.cn/design-patterns/decorator

模式实现

1.定义iPhone接口

主要定义了iPhone模板的说明接口方法getDesc,后续以这个方法为核心,展开嵌套。

package com.example.designpattern.decorator;

/**
 * 手机
 *
 * @author hongcunlin
 */
public interface Phone {
    /**
     * 介绍
     *
     * @return 介绍内容
     */
    String getDesc();
}

2.实现iPhone接口

简单试下getDesc的方法,目前是一个裸机的iPhone。

package com.example.designpattern.decorator.impl;

import com.example.designpattern.decorator.Phone;

/**
 * 苹果手机iPhone 14 Pro Max
 *
 * @author hongcunlin
 */
public class Iphone implements Phone {
    @Override
    public String getDesc() {
        return "iPhone";
    }
}

3.定义iPhone装饰器抽象类

装饰器的超类,里边存放iPhone属性,围绕它进行嵌套。

package com.example.designpattern.decorator.impl.decorator;

import com.example.designpattern.decorator.Phone;

/**
 * 手机装饰器
 *
 * @author hongcunlin
 */
public abstract class IphoneDecorator implements Phone {
    /**
     * 手机(抽象类存在的意义,否则就使用接口了)
     */
    protected Phone phone;

    /**
     * 构造方法
     *
     * @param phone 手机
     */
    IphoneDecorator(Phone phone) {
        this.phone = phone;
    }
}

4.1.实现iPhone装饰器之保护壳

嵌套一

package com.example.designpattern.decorator.impl.decorator;

import com.example.designpattern.decorator.Phone;

/**
 * iPhone保护壳
 *
 * @author hongcunlin
 */
public class IphoneCaseDecorator extends IphoneDecorator {
    /**
     * 构造方法
     *
     * @param phone 手机
     */
    public IphoneCaseDecorator(Phone phone) {
        super(phone);
    }

    @Override
    public String getDesc() {
        return "带保护壳的" + phone.getDesc();
    }
}

4.2.实现iPhone装饰器之无线充

嵌套二

package com.example.designpattern.decorator.impl.decorator;

import com.example.designpattern.decorator.Phone;

/**
 * iPhone无线充
 *
 * @author hongcunlin
 */
public class IphoneChargerDecorator extends IphoneDecorator {
    /**
     * 构造方法
     *
     * @param phone 手机
     */
    public IphoneChargerDecorator(Phone phone) {
        super(phone);
    }

    @Override
    public String getDesc() {
        return "带无线充的" + phone.getDesc();
    }
}

5.测试

这里我们先初始化一个iPhone,接着带上保护壳看看效果,最后再带上无线充看看效果。

package com.example.designpattern.decorator;

import com.example.designpattern.decorator.impl.Iphone;
import com.example.designpattern.decorator.impl.decorator.IphoneCaseDecorator;
import com.example.designpattern.decorator.impl.decorator.IphoneChargerDecorator;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class DesignPatternTest {
    @Test
    public void test() {
        // 常规iPhone
        Phone iphone = new Iphone();
        System.out.println(iphone.getDesc());

        // 带保护壳的iPhone
        iphone = new IphoneCaseDecorator(iphone);
        System.out.println(iphone.getDesc());

        // 带无线充的带保护壳的iPhone
        iphone = new IphoneChargerDecorator(iphone);
        System.out.println(iphone.getDesc());
    }
}

可以看到,随着装饰器的层层嵌套,iPhone的模样越来越复杂,是符合我们的预期的。

最后

装饰器主要是通过组合的模式,对类内容进行扩展,而不是通过继承的方式,特别是在Java只能单继承的情况,行之有效。

后面有空接着闲聊23种设计模式中的其他种。

相关内容

热门资讯

如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
施耐德电气数据中心整体解决方案... 近日,全球能效管理专家施耐德电气正式启动大型体验活动“能效中国行——2012卡车巡展”,作为该活动的...
20个非常棒的扁平设计免费资源 Apple设备的平面图标PSD免费平板UI 平板UI套件24平图标Freen平板UI套件PSD径向平...
德国电信门户网站可实时显示全球... 德国电信周三推出一个门户网站,直观地实时提供其安装在全球各地的传感器网络检测到的网络攻击状况。该网站...
为啥国人偏爱 Mybatis,... 关于 SQL 和 ORM 的争论,永远都不会终止,我也一直在思考这个问题。昨天又跟群里的小伙伴进行...
《非诚勿扰》红人闫凤娇被曝厕所... 【51CTO.com 综合消息360安全专家提醒说,“闫凤娇”、“非诚勿扰”已经被黑客盯上成为了“木...
2012年第四季度互联网状况报... [[71653]]  北京时间4月25日消息,据国外媒体报道,全球知名的云平台公司Akamai Te...