导航
1前言
4桥接模式
5总结
1 前言
在我的记忆里,桥总能发挥巨大价值。小时候,小河上的一座小桥连通了两个村寨,祖祖辈辈的乡亲们从桥上过,把青石板磨得圆润光滑。初中,我离开了小县城,每次汽车都要花一小时下一段险而长的盘山公路,山顶上立了一块纪念碑,上面刻着因修这段盘山路而牺牲的烈士们的名字。后来随着国家经济的发展,在这段盘山公路的峡谷上修了一座当时亚洲最大的吊索桥,通车后的车程从原来的一小时变成了五分钟,这座吊索桥的名字叫矮寨大桥。来源:https://www.wubayue.com
2 通过继承实现扩展
为了循序渐进的阐述清楚桥接模式,我们先从类的继承说起,继承是面向对象的三大特性(封装、继承、多态)之一,在平时开发中使用广泛,比如一些公共的逻辑可放在父类中供不同的子类复用,此处就是一个典型的继承示例。
// 服装
public abstract class Clothing
{
// 生产
public abstract void Produce();
}
// T恤
public class TShirt : Clothing
{
// 生产T恤
public override void Produce()
{
Console.WriteLine("生产T恤");
}
}
// 牛仔裤
public class Jeans : Clothing
{
// 生产牛仔裤
public override void Produce()
{
Console.WriteLine("生产牛仔裤");
}
}
// 调用
static void Main(string[] args)
{
// 生产T恤
Clothing tShirt = new TShirt();
tShirt.Produce();
// 生产牛仔裤(对于调用者来说,面向抽象类“服装”进行编程,符合开闭原则)
Clothing jeans = new Jeans();
jeans.Produce();
}
使用继承有两个显而易见的好处,一是代码复用,比如T恤和牛仔裤同属于服装就必然具有共性,在父类中封装共性就提升了代码的复用。二是对于调用者来说,更符合开闭原则,如代码所示,不论服装下的子类如何扩展,调用者使用的始终是服装这个抽象父类,无需修改调用代码。来源:https://www.wubayue.com
3 通过组合实现扩展
继承支持的是纵向的子类扩展,比如在服装下还可以扩展出西装、运动装、羽绒服等,它们与服装均是父子关系,服装的类型确认后不太容易发生变化,比如波司登的羽绒服,李宁的运动装,一卖就是几代人。还有一种非常重要的横向关联,比如颜色,款式等,这种横向关联通常具有更多的选择与变化,相对于继承也更为灵活,会根据流行元素、市场需求动态搭配组合。
// T恤
public class TShirt
{
// 颜色
public IColor? Color { get; set; } = null;
// 款式
public IStyle? Style { get; set; } = null;
// 生产T恤
public void Produce()
{
Console.WriteLine("生产T恤");
}
}
// 颜色
public interface IColor
{
// 染色
void Dye();
}
// 红色
public class RedColor : IColor
{
public void Dye()
{
Console.WriteLine("染红色");
}
}
// 蓝色
public class BlueColor : IColor
{
public void Dye()
{
Console.WriteLine("染蓝色");
}
}
// 款式
public interface IStyle
{
// 设计
void Design();
}
// 男式
public class MenStyle : IStyle
{
public void Design()
{
Console.WriteLine("男式设计");
}
}
// 女式
public class WomenStyle : IStyle
{
public void Design()
{
Console.WriteLine("女式设计");
}
}
// 调用
static void Main(string[] args)
{
Bridge.BeforeCombination.TShirt tShirt = new Bridge.BeforeCombination.TShirt();
// 颜色
Bridge.BeforeCombination.IColor red = new Bridge.BeforeCombination.RedColor();
tShirt.Color = red;
// 款式
Bridge.BeforeCombination.IStyle style = new Bridge.BeforeCombination.WomenStyle();
tShirt.Style = style;
// 开始生产
tShirt.Style.Design();
tShirt.Produce();
tShirt.Color.Dye();
}
所谓在家靠父母,出门靠朋友,继承就像父子关系,从一而终,组合则像朋友关系,多多益善。因此在软件开发中正确的定义对象之间的继承与组合关系尤为重要,总体来说组合要优于继承,下面的表格中对比了继承与组合的定义以及优缺点:来源:https://www.wubayue.com
特性 | 继承 | 组合 |
---|---|---|
关系 | 继承是“is-a”的关系,比如“T-shirt is a clothing” | 组合是“has-a”的关系,比如“T-shirt has a color” |
耦合度 | 高 | 低 |
灵活性 | 编译时确定,不够灵活 | 运行时可改变,灵活 |
设计复杂度 | 可能导致多重继承 | 结构更扁平 |
4 桥接模式
了解了继承与组合,再来看桥接模式就非常简单了,当在设计中即有继承,又有组合,那么桥接模式提供了一个范式将二者接合:来源:https://www.wubayue.com
// 服装
public abstract class Clothing
{
// 颜色
public IColor? Color { get; set; } = null;
// 生产
public abstract void Produce();
}
// T恤
public class TShirt : Clothing
{
// 生产T恤
public override void Produce()
{
Console.WriteLine("生产T恤");
}
}
// 牛仔裤
public class Jeans : Clothing
{
// 生产牛仔裤
public override void Produce()
{
Console.WriteLine("生产牛仔裤");
}
}
// 颜色
public interface IColor
{
// 染色
void Dye();
}
// 红色
public class RedColor : IColor
{
public void Dye()
{
Console.WriteLine("染红色");
}
}
// 蓝色
public class BlueColor : IColor
{
public void Dye()
{
Console.WriteLine("染蓝色");
}
}
// 调用
static void Main(string[] args)
{
// 生产红色的T恤
Clothing tShirt = new TShirt();
IColor red = new RedColor();
tShirt.Color = red;
tShirt.Produce();
tShirt.Color.Dye();
// 生产蓝色的牛仔裤
Clothing jeans = new Jeans();
IColor blue = new BlueColor();
jeans.Color = blue;
jeans.Produce();
jeans.Color.Dye();
}
5 总结
桥接模式适用于特定的业务场景,假如你是一个服装生产的老板,专做单品,T恤、牛仔裤、运动装虽然都做,但每类只做一款单品,此时使用继承简单派生即可。假如你是一个专一的老板只做一个品类,但把这个品类做出了花,比如虽然只做T恤,但有不同的尺码、颜色、材质、款式、亲子、文创等,此时使用组合灵活搭配即可。只有当你即追求多品类,又要把每个品类都做出花时,那就需要桥接模式了。来源:https://www.wubayue.com
<全文完>