【设计模式】桥接模式

本文探讨了如何使用桥接模式解决软件系统中多维度变化的问题,通过实例对比展示了如何避免类膨胀,并在游戏开发和图形绘制中应用此模式。桥接模式的优点在于提高系统可扩展性和降低复杂度,但设计时需要注意理解和识别变化维度。
摘要由CSDN通过智能技术生成

使用频率【3星】

一、概念

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

二、解决问题

在软件系统中,有些类型由于自身的逻辑,它具有两个或多个维度的变化。为了解决这种多维度变化,又不引入复杂度,就可以使用桥接模式。

三、对象

1、抽象类(Abstraction):定义抽象接口,它一般是抽象类而不是接口。该接口中包含实现具体行为、具体特征的Implementor接口。

2、扩充的抽象类(RefinedAbstraction):继承自Abstraction的子类,通常情况下它不再是抽象类而是具体类,它实现了在Abstraction中声明的抽象业务方法,在该对象中可以调用在Implementor中定义的业务方法。

3、实现类(Implementor):定义具体行为,具体特征的应用接口。

4、具体实现类(ConcreteImplementor):实现Implementor。

四、实现代码

1、未使用桥接模式。

一个游戏,主角身体里住着三个灵魂,它可以切换成对应的三种形态,来施放不同的技能。三种灵魂定义如下


public interface ISoul
{
	void CastSkill();
}
 
public class Mage : ISoul
{
	public void CastSkill()
	{
		Debug.Log ("Summon a box");
	}
}
 
public class Hunter : ISoul
{
	public void CastSkill()
	{
		Debug.Log ("Fire arrow");
	}
}
 
public class Warrior : ISoul
{
	public void CastSkill()
	{
		Debug.Log ("Power of Thor");
	}
}

但是身体只有一个,所以需要切换形态。貌似我们可以使用switch case语句来完成这个任务:【工厂方法模式】


public enum SoulType
{
	Mage,
	Hunter,
	Warrior,
}
public class Hero
{
	private Mage _mage = new Mage();
	private Hunter _hunter = new Hunter();
	private Warrior _warrior = new Warrior();
	private SoulType _soulType = SoulType.Mage;
	public void CastSkill()
	{
		ISoul activeSoul = null;
		switch (_soulType) {
		case SoulType.Mage:
			activeSoul = _mage;
			break;
		case SoulType.Hunter:
			activeSoul = _hunter;
			break;
		case SoulType.Warrior:
			activeSoul = _warrior;
			break;
		}
		activeSoul.CastSkill ();
	}
	public void ChangeSoul(SoulType soulType)
	{
		_soulType = soulType;
	}
}

//使用:
Hero hero = new Hero ();
		hero.ChangeSoul (SoulType.Hunter);
		hero.CastSkill ();

通过以上代码,我们会发现,再增加一个技能的形态,需要修改Hero的CasterSkill(),不符合开闭原则【可以拓展,但是尽量不修改原有的逻辑】。

2、桥接模式

接口和技能的形态类不修改,可以把Hero修改成以下的类

public class TrineHero
{
	private ISoul _soul;
	public void CastSkill()
	{
		_soul.CastSkill ();
	}
 
	public void ChangeSoul<T>() where T:ISoul, new()
	{
		_soul = new T();
	}
}
//使用修改成:
TrineHero th = new TrineHero ();
		th.ChangeSoul<Mage> ();
		th.CastSkill ();

增加一个新的技能形态,就可以新增一个技能的类

public class Priest : ISoul
{
	public void CastSkill()
	{
		Console.WriteLine ("Mind control");
	}
}

切换技能

//使用修改成:
TrineHero th = new TrineHero ();
th.ChangeSoul<Mage> ();
th.CastSkill ();
//切换不同技能
th.ChangeSoul<Priest> ();
th.CastSkill ();

总结:以上 例子当中

抽象类/接口类(Abstraction):TrineHero

扩充的抽象类(RefinedAbstraction):Priest 

实现类(Implementor):ISoul

具体实现类(ConcreteImplementor):Mage 三种技能

 

例子2

using System;
 
namespace ConsoleApp2
{
    class Class1
    {
        static void Main(string[] args)
        {
            //白色
            Color white = new White();
            //正方形
            Shape square = new Square();
            //白色的正方形
            square.SetColor(white);
            square.Draw();
 
            //长方形
            Shape rectange = new Rectangle();
            rectange.SetColor(white);
            rectange.Draw();
 
            Console.ReadLine();
        }
    }
 
    public abstract class Shape
    {
        public Color color;
        public void SetColor(Color color)
        {
            this.color = color;
        }
        public abstract void Draw();
    }
 
    public class Circle : Shape
    {
        public override void Draw()
        {
            color.Bepaint("正方形");
        }
    }
    public class Rectangle : Shape
    {
 
        public override void Draw()
        {
            color.Bepaint("长方形");
        }
    }
 
    public class Square : Shape
    {
        public override void Draw()
        {
            color.Bepaint("正方形");
        }
    }
 
    public interface Color
    {
        void Bepaint(string shape);
    }
 
    public class White : Color
    {
        public void Bepaint(string shape)
        {
            Console.WriteLine("白色的" + shape);
        }
    }
 
    public class Gray : Color
    {
        public void Bepaint(string shape)
        {
            Console.WriteLine("灰色的" + shape);
        }
    }
 
    public class Black : Color
    {
        public void Bepaint(string shape)
        {
            Console.WriteLine("黑色的" + shape);
        }
    }
}

总结:

抽象类/接口类(Abstraction):Shape

扩充的抽象类(RefinedAbstraction):Circle --继承shape

实现类(Implementor):Color

具体实现类(ConcreteImplementor):Black 

说明:两个例子表示的两种桥接的使用情况,第一种是相同类型逻辑的扩展,第二种是两种不同逻辑的扩展

五、优缺点

 5.1 优点

  • 降低了沿着两个或多个维度扩展时的复杂度,防止类的过度膨胀
  • 桥接模式提高了系统的可扩充性,在两个变化维度中任意扩展一个维度,都不需要修改原有系统

 5.2 缺点

  • 桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。
  • 桥接模式要求正确识别出系统中两个独立变化的维度,因此其使用范围具有一定的局限性。

六、使用场景

  • 当一个对象有多个变化因素时,可以考虑使用桥接模式,通过抽象这些变化因素,将依赖具体实现修改为依赖抽象。
  • 当我们期望一个对象的多个变化因素可以动态变化,而且不影响客户端的程序使用时。
  • 如果使用继承的实现方案,会导致产生很多子类,任何一个变化因素都需要产生多个类来完成,就要考虑桥接模式。
  • 游戏开发中一个武器有多种变化形态,可以考虑使用桥接模式。

 

 

设计模式系列博客,主要参考大话设计模式,以及一些博客内容

https://blog.csdn.net/qq826364410/article/details/88143521

https://blog.csdn.net/ecidevilin/article/details/52669475

https://www.runoob.com/design-pattern/bridge-pattern.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值