dart设计模式之适配器模式,桥接模式,装饰器模式

简介: 这是我参与8月更文挑战的第15天,活动详情查看:8月更文挑战。为应掘金的八月更文挑战,适配器模式模式分析适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。 这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。举个真实的例子,读卡器是作为内存卡和笔记本之间的适配器。您将内存卡插入读卡器,再将读卡器插入笔记本,这样就可以通过笔记本来读取内存卡。 我们通过下面的实例来演示适配器模式的使用。其中,音频播放器设备只能播放 mp3 文件,通过使用一个更高级的音频播放器来播放 vlc 和 mp4 文

适配器模式

模式分析

适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。 这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。举个真实的例子,读卡器是作为内存卡和笔记本之间的适配器。您将内存卡插入读卡器,再将读卡器插入笔记本,这样就可以通过笔记本来读取内存卡。 我们通过下面的实例来演示适配器模式的使用。其中,音频播放器设备只能播放 mp3 文件,通过使用一个更高级的音频播放器来播放 vlc 和 mp4 文件。

模式难点

模式解决问题

主要解决在软件系统中,常常要将一些"现存的对象"放到新的环境中,而新环境要求的接口是现对象不能满足的。

优点

  1. 可以让任何两个没有关联的类一起运行。
  2. 提高了类的复用。
  3. 增加了类的透明度。
  4. 灵活性好。

缺点

  1. 过多地使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是 A 接口,其实内部被适配成了 B 接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。 2.由于 JAVA 至多继承一个类,所以至多只能适配一个适配者类,而且目标类必须是抽象类。

模式应用场景

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

模式代码

import 'run.dart';
//官方媒体播放接口
abstract class MediaPlayer {
  void play(String audioType, String fileName);
}
//自定义媒体播放接口
abstract class AdvancedMediaPlayer {
  void playVlc(String fileName);
  void playMp4(String fileName);
}
//创建实现了 AdvancedMediaPlayer 接口的实体类。
class VlcPlayer implements AdvancedMediaPlayer {
  @override
  void playMp4(String fileName) {}
  @override
  void playVlc(String fileName) {
    print("Playing vlc file. Name: " + fileName);
  }
}
class Mp4Player implements AdvancedMediaPlayer {
  @override
  void playVlc(String fileName) {
    //什么也不做
  }
  @override
  void playMp4(String fileName) {
    print("Playing mp4 file. Name: " + fileName);
  }
}
// 创建实现了 MediaPlayer 接口的适配器类。
class MediaAdapter implements MediaPlayer {
  AdvancedMediaPlayer advancedMusicPlayer;
  MediaAdapter(String audioType) {
    if (audioType == "vlc") {
      advancedMusicPlayer = new VlcPlayer();
    } else if (audioType == "mp4") {
      advancedMusicPlayer = new Mp4Player();
    }
  }
  @override
  void play(String audioType, String fileName) {
    if (audioType == "vlc") {
      advancedMusicPlayer.playVlc(fileName);
    } else if (audioType == "mp4") {
      advancedMusicPlayer.playMp4(fileName);
    }
  }
}
// 创建实现了 MediaPlayer 接口的实体类。
class AudioPlayer implements MediaPlayer {
  MediaAdapter mediaAdapter;
  @override
  void play(String audioType, String fileName) {
    //播放 mp3 音乐文件的内置支持
    if (audioType == "mp3") {
      print("Playing mp3 file. Name: " + fileName);
    }
    //mediaAdapter 提供了播放其他文件格式的支持
    else if (audioType == "vlc" || audioType == "mp4") {
      mediaAdapter = new MediaAdapter(audioType);
      mediaAdapter.play(audioType, fileName);
    } else {
      print("Invalid media. " + audioType + " format not supported");
    }
  }
}
class RunAdapter implements Run {
  @override
  main() {
    AudioPlayer audioPlayer = new AudioPlayer();
    audioPlayer.play("mp3", "beyond the horizon.mp3");
    audioPlayer.play("mp4", "alone.mp4");
    audioPlayer.play("vlc", "far far away.vlc");
    audioPlayer.play("avi", "mind me.avi");
  }
  @override
  String name = "适配器模式";
}
复制代码

桥接模式(Bridge)

模式分析

桥接(Bridge)是用于把抽象化与实现化解耦,使得二者可以独立变化。这种类型的设计模式属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。

这种模式涉及到一个作为桥接的接口,使得实体类的功能独立于接口实现类。这两种类型的类可被结构化改变而互不影响。

我们通过下面的实例来演示桥接模式(Bridge Pattern)的用法。其中,可以使用相同的抽象类方法但是不同的桥接实现类,来画出不同颜色的圆。

模式难点

模式解决问题

在有多种可能会变化的情况下,用继承会造成类爆炸问题,扩展起来不灵活。

优点

  1. 抽象和实现的分离。
  2. 优秀的扩展能力。
  3. 实现细节对客户透明。

缺点

桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。

模式应用场景

  1. 如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系,通过桥接模式可以使它们在抽象层建立一个关联关系。
  2. 对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用。
  3. 一个类存在两个独立变化的维度,且这两个维度都需要进行扩展。

模式代码

//咖啡售卖系统中,容量作为抽象化(Abstraction),口味作为实现化(Implementor)
//创建口味接口
abstract class ICoffeeAdditives {
  void addSomething();
}
// 创建抽象化类
abstract class Coffee {
  ICoffeeAdditives additives;
  Coffee(this.additives);
  void orderCoffee(int count);
}
//修正抽象化类,增加品控方法
abstract class RefinedCoffee extends Coffee {
  RefinedCoffee(ICoffeeAdditives additives) : super(additives);
  checkQuality(int score) {
    print("添加" + score.toString() + "%");
  }
}
//创建实现化部分
class Milk implements ICoffeeAdditives {
  @override
  void addSomething() {
    print("加奶");
  }
}
class Sugar implements ICoffeeAdditives {
  @override
  void addSomething() {
    print("加糖");
  }
}
class LargeCoffee extends RefinedCoffee {
  LargeCoffee(ICoffeeAdditives additives) : super(additives);
  @override
  void orderCoffee(int count) {
    additives.addSomething();
    print("大杯咖啡" + count.toString() + "杯");
  }
}
class MidCoffee extends RefinedCoffee {
  MidCoffee(ICoffeeAdditives additives) : super(additives);
  @override
  void orderCoffee(int count) {
    additives.addSomething();
    print("中杯咖啡" + count.toString() + "杯");
  }
}
class RunBridge implements Run {
  @override
  String name = "桥接模式";
  @override
  main() {
    RefinedCoffee largeWithMilk = new LargeCoffee(Milk());
    largeWithMilk.orderCoffee(2);
    largeWithMilk.checkQuality(90);
    print("\n");
    RefinedCoffee largeWithSugar = new MidCoffee(Sugar());
    largeWithSugar.orderCoffee(1);
    largeWithSugar.checkQuality(100);
  }
}
复制代码

装饰器模式(Decorator Pattern)

模式分析

装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。

这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。

我们通过下面的实例来演示装饰器模式的用法。其中,我们将把一个形状装饰上不同的颜色,同时又不改变形状类。

模式难点

实现现有抽象对象并传入已实现的抽象对象,并加入自定义方法

模式解决问题

一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。

优点

装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。

缺点

多层装饰比较复杂。

模式应用场景

  1. 扩展一个类的功能。
  2. 动态增加功能,动态撤销。

模式代码

//创建接口
abstract class Shape {
  void draw();
}
//创建接口实体类
class Rectangle implements Shape {
  @override
  void draw() {
    print("shape: Rectangle");
  }
}
class Circle implements Shape {
  @override
  void draw() {
    print("shape: Circle");
  }
}
//创建实现了Shape接口的抽象类
class ShapeDecorator implements Shape {
  final Shape decoratedShape;
  ShapeDecorator(this.decoratedShape);
  @override
  void draw() {
    decoratedShape.draw();
  }
}
//创建扩展了 ShapeDecorator 类的实体装饰类。
class RedShapeDecorator extends ShapeDecorator {
  RedShapeDecorator(Shape decoratedShape) : super(decoratedShape);
  @override
  void draw() {
    decoratedShape.draw();
    _setRedBorder(decoratedShape);
  }
  void _setRedBorder(Shape decoratedShape) {
    print("Border Color: Red");
  }
}
//使用 RedShapeDecorator 来装饰 Shape 对象。
class RunDecorator implements Run {
  @override
  void main() {
    Shape circle = new Circle();
    // ShapeDecorator redCircle = new RedShapeDecorator(new Circle());
    // ShapeDecorator redRectangle = new RedShapeDecorator(new Rectangle());
    Shape redCircle = new RedShapeDecorator(new Circle());
    Shape redRectangle = new RedShapeDecorator(new Rectangle());
    print("Circle with normal border");
    circle.draw();
    print("\nCircle of red border");
    redCircle.draw();
    print("\nRectangle of red border");
    redRectangle.draw();
  }
  @override
  String name = "装饰器模式";
}



相关文章
|
19天前
|
设计模式 Java 开发者
「全网最细 + 实战源码案例」设计模式——适配器模式
适配器模式(Adapter Pattern)是一种结构型设计模式,通过引入适配器类将一个类的接口转换为客户端期望的另一个接口,使原本因接口不兼容而无法协作的类能够协同工作。适配器模式分为类适配器和对象适配器两种,前者通过多重继承实现,后者通过组合方式实现,更常用。该模式适用于遗留系统改造、接口转换和第三方库集成等场景,能提高代码复用性和灵活性,但也可能增加代码复杂性和性能开销。
67 28
|
17天前
|
设计模式 前端开发 数据库
「全网最细 + 实战源码案例」设计模式——桥接模式
桥接模式(Bridge Pattern)是一种结构型设计模式,通过将抽象部分与实现部分分离,使它们可以独立变化,从而降低代码耦合度,避免类爆炸,提高可扩展性。其结构包括实现类接口、具体实现类、抽象类和精确抽象类。适用于多维度扩展类、隐藏实现细节、简化庞杂类以及运行时切换实现方法的场景。优点包括高扩展性、隐藏实现细节、遵循开闭原则和单一职责原则;缺点是可能增加代码复杂度。示例中展示了不同操作系统播放不同格式视频文件的实现。
47 19
|
4月前
|
设计模式 XML Java
【设计模式】装饰器模式(定义 | 特点 | Demo入门讲解)
【设计模式】装饰器模式(定义 | 特点 | Demo入门讲解)
54 0
|
2月前
|
设计模式 前端开发 JavaScript
前端必须掌握的设计模式——装饰器模式
装饰器模式是一种结构型设计模式,通过创建新类来包装原始对象,实现在不修改原有结构的前提下扩展新行为。其核心在于“组合”思想,使新功能可“即插即拔”。该模式具有解耦性、灵活性和动态性等特点,广泛应用于类的面向对象编程语言中,如JavaScript的注解和TypeScript的写法。示例中,通过装饰器模式为游戏角色动态添加装备,展示了其强大的扩展性和灵活性。
|
2月前
|
设计模式 JSON 前端开发
前端必须掌握的设计模式——适配器模式
适配器模式是一种结构型设计模式,用于使接口不兼容的对象能够相互合作。通过在客户端和系统之间引入一个“中间层”适配器,将不同类型的输入数据转换为系统能处理的标准格式,减轻系统的负担,提高扩展性和可维护性。例如,MacBook的扩展坞将多种接口(如HDMI、USB)转换为Type-C接口,实现多接口兼容。
|
4月前
|
设计模式 PHP 开发者
PHP中的设计模式:桥接模式的解析与应用
在软件开发的浩瀚海洋中,设计模式如同灯塔一般,为开发者们指引方向。本文将深入探讨PHP中的一种重要设计模式——桥接模式。桥接模式巧妙地将抽象与实现分离,通过封装一个抽象的接口,使得实现和抽象可以独立变化。本文将阐述桥接模式的定义、结构、优缺点及其应用场景,并通过具体的PHP示例代码展示如何在实际项目中灵活运用这一设计模式。让我们一起走进桥接模式的世界,感受它的魅力所在。
|
5月前
|
设计模式 Java
Java设计模式-装饰器模式(10)
Java设计模式-装饰器模式(10)
|
5月前
|
设计模式 Java 程序员
Java设计模式-适配器模式(8)
Java设计模式-适配器模式(8)
|
5月前
|
设计模式 自然语言处理 算法
PHP中的设计模式:桥接模式的深入探索与应用
在PHP开发中,理解并运用设计模式是提升代码质量与可维护性的关键。本文聚焦于桥接模式——一种结构型设计模式,它通过封装一个抽象的接口,将实现与抽象分离,从而使得它们可以独立变化。不同于传统摘要的概述式表述,本文将以故事化的情境引入,逐步解析桥接模式的精髓,通过PHP代码示例详细展示其在实际项目中的应用,旨在为读者提供一个既深刻又易于理解的学习体验。
41 1
|
5月前
|
设计模式 Java
Java设计模式-桥接模式(9)
Java设计模式-桥接模式(9)

热门文章

最新文章