首页 > 其他分享 >桥接模式

桥接模式

时间:2024-02-28 11:12:08浏览次数:34  
标签:咖啡 桥接 ICoffee 模式 实现 抽象 部分

简介

桥接模式(Bridge Pattern)是一种结构型设计模式,它主要用于将抽象部分与实现部分分离,从而使它们可以独立变化。桥接模式通过将继承关系转化为组合关系,使得抽象部分和实现部分可以独立地变化,不会相互影响。

在桥接模式中,抽象部分通常指的是一个抽象类或接口,它定义了对外的接口或抽象方法;而实现部分则是具体的实现类,实现了抽象部分定义的接口或抽象方法。

桥接模式的核心思想是将抽象部分和实现部分解耦,使得它们可以独立地变化和扩展,同时通过组合关系而不是继承关系来实现这种解耦,从而提高了系统的灵活性和可维护性。

案例

让我们来考虑一个更具体的生活场景:咖啡店的点单系统。

假设你经营一家咖啡店,你想设计一个点单系统,该系统可以根据顾客的要求制作出不同种类的咖啡。咖啡的种类有很多,比如美式咖啡、拿铁、卡布奇诺等,同时每种咖啡可以选择不同的配料,比如牛奶、糖、焦糖等。在这种情况下,你可以使用桥接模式来设计点单系统。

让我们看看如何使用C#实现这个例子:

using System;

// 抽象部分:咖啡
interface ICoffee
{
    void MakeCoffee();
}

// 具体实现部分:美式咖啡
class Americano : ICoffee
{
    public void MakeCoffee()
    {
        Console.WriteLine("制作美式咖啡");
    }
}

// 具体实现部分:拿铁
class Latte : ICoffee
{
    public void MakeCoffee()
    {
        Console.WriteLine("制作拿铁");
    }
}

// 抽象部分:配料
interface IAdditive
{
    void Add();
}

// 具体实现部分:牛奶
class Milk : IAdditive
{
    public void Add()
    {
        Console.WriteLine("加牛奶");
    }
}

// 具体实现部分:糖
class Sugar : IAdditive
{
    public void Add()
    {
        Console.WriteLine("加糖");
    }
}

// 桥接部分:咖啡和配料的组合
class CoffeeWithAdditive : ICoffee
{
    private readonly ICoffee coffee;
    private readonly IAdditive additive;

    public CoffeeWithAdditive(ICoffee coffee, IAdditive additive)
    {
        this.coffee = coffee;
        this.additive = additive;
    }

    public void MakeCoffee()
    {
        coffee.MakeCoffee();
        additive.Add();
    }
}

class Program
{
    static void Main(string[] args)
    {
        // 制作一杯美式咖啡
        ICoffee americano = new Americano();
        americano.MakeCoffee();

        // 制作一杯拿铁咖啡
        ICoffee latte = new Latte();
        latte.MakeCoffee();

        // 制作一杯拿铁咖啡加牛奶
        ICoffee latteWithMilk = new CoffeeWithAdditive(new Latte(), new Milk());
        latteWithMilk.MakeCoffee();

        // 制作一杯美式咖啡加糖
        ICoffee americanoWithSugar = new CoffeeWithAdditive(new Americano(), new Sugar());
        americanoWithSugar.MakeCoffee();
    }
}

在这个例子中,ICoffee 接口代表咖啡,AmericanoLatte 是具体的咖啡种类。IAdditive 接口代表配料,MilkSugar 是具体的配料种类。CoffeeWithAdditive 类则是将咖啡和配料组合起来的桥接部分。通过组合不同的咖啡和配料,可以制作出不同种类的咖啡,而不需要在每个咖啡类中重复编写配料的代码,从而提高了代码的复用性和可维护性。

增加维度

如果在上述的咖啡店点单系统中再加一个维度,比如大中小杯的选择,我们可以考虑使用桥接模式来处理这个场景。在这种情况下,我们需要将杯型作为一个维度,与咖啡和配料进行组合。

首先,我们可以定义一个表示杯型的接口或抽象类,然后具体实现大中小杯的类。接着,我们需要修改咖啡和配料类,使其可以接受一个杯型对象作为参数,从而与杯型进行组合。最后,我们可以通过组合不同种类的咖啡、配料和杯型,来制作出各种不同的咖啡饮品。

以下是对代码的修改示例:

using System;
using System.Collections.Generic;

// 抽象部分:咖啡
interface ICoffee
{
    void Make();
}

// 具体实现部分:美式咖啡
class Americano : ICoffee
{
    public void Make()
    {
        Console.WriteLine("制作美式咖啡");
    }
}

// 具体实现部分:拿铁
class Latte : ICoffee
{
    public void Make()
    {
        Console.WriteLine("制作拿铁");
    }
}

// 抽象部分:配料
interface IAdditive
{
    void Add();
}

// 具体实现部分:牛奶
class Milk : IAdditive
{
    public void Add()
    {
        Console.WriteLine("加牛奶");
    }
}

// 具体实现部分:糖
class Sugar : IAdditive
{
    public void Add()
    {
        Console.WriteLine("加糖");
    }
}

// 抽象部分:杯型
interface ICup
{
    string Size { get; }
}

// 具体实现部分:大杯
class LargeCup : ICup
{
    public string Size => "大杯";
}

// 具体实现部分:中杯
class MediumCup : ICup
{
    public string Size => "中杯";
}

// 具体实现部分:小杯
class SmallCup : ICup
{
    public string Size => "小杯";
}

// 桥接部分:咖啡和配料的组合
class CoffeeWithAdditive : ICoffee
{
    private readonly ICoffee coffee;
    private readonly IAdditive additive;
    private readonly ICup cup;

    public CoffeeWithAdditive(ICoffee coffee, IAdditive additive, ICup cup)
    {
        this.coffee = coffee;
        this.additive = additive;
        this.cup = cup;
    }

    public void Make()
    {
        Console.WriteLine($"制作{cup.Size}{coffee.GetType().Name}");
        coffee.Make();
        additive.Add();
    }
}

class Program
{
    static void Main(string[] args)
    {
        // 制作一个中杯拿铁
        ICoffee latte = new CoffeeWithAdditive(new Latte(), new Milk(), new MediumCup());
        latte.Make();

        Console.WriteLine();

        // 制作一个大杯美式咖啡加糖
        ICoffee americano = new CoffeeWithAdditive(new Americano(), new Sugar(), new LargeCup());
        americano.Make();
    }
}

在这个修改后的示例中,我们引入了 ICup 接口表示杯型,以及具体的大中小杯实现类 LargeCupMediumCupSmallCup。然后在 CoffeeWithAdditive 类中,我们将 ICup 作为一个额外的参数,与咖啡和配料一起组合。最后,在 Main 方法中,我们可以通过组合不同的咖啡、配料和杯型来制作出各种不同的咖啡饮品。

优点:

  1. 解耦抽象与实现: 桥接模式通过将抽象部分与实现部分分离,使得它们可以独立变化,不会相互影响,从而实现了解耦。

  2. 更好的扩展性: 桥接模式使得抽象部分和实现部分可以独立扩展,系统可以灵活地增加新的抽象部分或实现部分,而不需要修改现有的代码。

  3. 隐藏实现细节: 桥接模式将实现部分隐藏在抽象部分之后,使得客户端只需关注抽象部分的接口,而不需要关注实现部分的细节,降低了系统的复杂度。

  4. 更好的复用性: 桥接模式将抽象部分和实现部分分离,使得它们可以独立变化和复用,提高了代码的复用性。

缺点:

  1. 增加系统复杂性: 桥接模式引入了抽象部分和实现部分之间的额外的桥接类,可能会增加系统的复杂性,使得代码结构变得更加复杂。

  2. 可能导致类爆炸: 如果系统中存在多个维度的变化,可能会产生大量的桥接类,导致类的数量急剧增加,使得系统变得难以管理和理解。

  3. 不易于理解: 桥接模式的概念较为抽象,需要一定的经验和理解才能正确地使用,可能会增加团队成员的学习成本。

  4. 适用场景有限: 桥接模式适用于存在多个维度变化的场景,如果系统中只有单一的变化维度,可能并不适合使用桥接模式,会增加不必要的复杂性。

适用场景:

  1. 抽象和实现之间存在多个变化维度: 当系统中某个类的抽象部分和实现部分都可以有多种变化时,可以使用桥接模式将它们分离开来,使得它们可以独立变化,不会相互影响。

  2. 不希望使用继承或子类化时: 当系统中存在多个维度的变化时,使用继承会导致类的爆炸性增长,而桥接模式可以通过组合来解决这个问题,避免使用继承或子类化。

  3. 需要动态选择实现时: 当系统需要在运行时选择不同的实现时,可以使用桥接模式将抽象部分与实现部分分离,通过组合来动态选择实现。

  4. 抽象和实现不应该固定在编译时: 当系统中的抽象部分和实现部分不应该在编译时固定下来,而应该在运行时动态选择时,可以使用桥接模式来实现这种需求。

  5. 需要隐藏实现细节时: 当系统需要隐藏实现细节,使得客户端只需关注抽象部分的接口时,可以使用桥接模式将实现部分隐藏在抽象部分之后。

标签:咖啡,桥接,ICoffee,模式,实现,抽象,部分
From: https://www.cnblogs.com/mchao/p/18039362

相关文章

  • KISS 原则 (设计模式)
    KISS定义kiss原则的英文描述又几个版本,计较下边的这几个keepitsimpleandstupid.keepitshortandsimplekeepitsimpleandstraightforward不过仔细看你会发现,他们表达的意思其实差不多,尽量保持简单。它是一个万金油的设计原则,可以在很多场景中,它不仅仅经常用来指......
  • 适配器模式
    简介适配器模式是一种结构型设计模式,它允许将一个类的接口转换成客户端所期望的另一个接口。适配器模式通常用于解决两个不兼容接口之间的兼容性问题,使得原本由于接口不匹配而无法一起工作的类能够协同工作。适配器模式主要由三个角色组成:目标接口(TargetInterface):客户端所期......
  • 原型模式
    定义:原型模式(PrototypeDesignPattern)用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型对象相同的新对象原型模式主要解决的问题: 如果创建对象的成本较大,比如对象中的数据是经过复杂计算才能得到的,或者需要从RPC接口或者数据库等比较慢的IO中获取,这种情况我们......
  • 原型模式
    简介原型模式(PrototypePattern)是一种创建型设计模式,它允许创建新对象的同时,通过复制现有对象的方式来初始化新对象。这意味着在原型模式中,新对象的创建过程不再依赖于直接实例化类,而是通过复制已有对象的方式来进行。在原型模式中,存在一个原型对象(Prototype),它是需要被复制的对......
  • 建造者模式
    简介建造者模式(BuilderPattern)是一种创建型设计模式,用于构建复杂对象。它的主要目的是将对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示形式。这种模式通常适用于创建对象的参数较多,且某些参数之间存在复杂的依赖关系的情况。在建造者模式中,通常会有一个建造......
  • C++特殊类的设计与单例模式
    //1.设计一个不能被拷贝的类/*解析:拷贝只会放生在两个场景中:拷贝构造函数以及赋值运算符重载,因此想要让一个类禁止拷贝,只需让该类不能调用拷贝构造函数以及赋值运算符重载即可。C++98;将拷贝构造函数与赋值运算符重载只声明不定义,并且将其访问权限设置为私有即......
  • 详解在 centos 中引导到救援模式
    详解在centos中引导到救援模式Linux系统CentOS进入单用户模式和救援模式详解一、概述目前在运维日常工作中,经常会遇到服务器异常断电、忘记root密码、系统引导文件损坏无法进入系统等等操作系统层面的问题,给运维带来诸多不便,现将上述现象的解决方法和大家分享一下,本次主要以C......
  • Ubuntu如何进救援模式
    linux的救援模式-1详解在Ubuntu中引导到救援模式或紧急模式这篇教程将介绍如何在Ubuntu22.04、20.04和18.04LTS版本中引导到救援Rescue模式或紧急Emergency模式。你可能已经知道,在RHEL7、RHEL8、Ubuntu16.04LTS及其更新的版本的Linux发行版中运行等级R......
  • 设计模式--观察者(Observer)模式
    目录概念概念观察者模式(ObserverPattern)是C++中常用的一种设计模式,它定义了对象间的一种一对多的依赖关系。在这种模式中,当一个对象(被观察者,Subject)的状态发生改变时,所有依赖于它的对象(观察者,Observer)都会收到通知并自动更新。这种模式的结构通常包括四个部分:抽象主题(Subject......
  • 接口隔离原则(设计模式)
    定义“Clientsshouldnotbeforcedtodependuponinterfacesthattheydonotuse”个人认为接口隔离原则,和单一原则有点像。一个接口实现一个功能。 不过,你应该已经发现,接口隔离原则跟单一职责原则有点类似,不过稍微还是有点区别。单一职责原则针对的是模块、类、接口......