vr全景网站开发制作,做网站的哪里好,中英文网站系统,云数据库安装wordpress一、为何需要桥接模式#xff08;Bridge#xff09;?
在软件设计中#xff0c;存在有两个或多个不同维度的模块时#xff0c;我们需要将这些模块使用到在一起#xff0c;来实现一个完整的功能。所谓不同维度的意思就是这些模块所负责的职责是不同的#xff0c;并且它们…一、为何需要桥接模式Bridge?
在软件设计中存在有两个或多个不同维度的模块时我们需要将这些模块使用到在一起来实现一个完整的功能。所谓不同维度的意思就是这些模块所负责的职责是不同的并且它们之间没有多大的关联性。
根据设计原则中的单一职责原则各自模块应当保持各自的分工任务。比如在画图系统中存在形状和画笔的两个维度。形状负责的是它的模样矩形、圆形、三角形等而画笔负责的是铅笔、毛笔、圆珠笔之类的选型。
倘若在某个维度的类里对另一维度的类有改写的痕迹就会对这个功能的扩展性以及维护性受到影响。
比如设计一个抽奖系统。员工、员工家属都参与抽奖奖金分为一二三等奖最后公布抽奖名单。其中中奖者和奖金是两个不同维度的模块。 以下例子就是个错误的设计暴露了对代码的扩展和维护困难的弊端。 // 方式一将中奖者类和奖金类作为继承关系互相受到影响public abstract class Bounds{public abstract string getOneGift();//一等奖礼品public abstract string getTwoGift();//二等奖礼品//扩展定义三等奖、安慰奖礼品等...}public class LuckyStaff:Bounds{public override string getOneGift(){return iPhone 15 Pro;}public override string getTwoGift(){return HUAWEI MatePad Pro 13.2;}//扩展实现 n 个 getXXXGift...}
//扩展其他中奖者public class LuckyFamilyMember:Bounds...
//方式一违反了单一职责原则
//LuckyStaff 类重写或实现了 Bounds 类的方法不应该直接处理 Bounds 的事情。//方式二将中奖者和奖金具体类直接作为对象组合关系互相受到影响public class LuckyStaff{private Bounds onebounds;private Bounds twobounds;//...public string getOneGift(){return onebounds.getOneGift();}public string getTwoGift(){return twobounds.getTwoGift();}//...}
//扩展其他中奖者public class LuckyFamilyMember...
//方式二违反了依赖倒置原则和迪米特法则
//违反依赖倒置原则当修改 Bounds 类的方法如移除方法就会影响 LuckyStaff
//违反迪米特法则Bounds 和 LuckyStaff 没有多大关联性却在代码中 LuckyStaff 过于依赖 Bounds从以上代码可看出如果以后再扩展不同身份的中奖者和不同的奖金类别就得需要在原来的代码结构中进行添加和修改或者再创建一个类重新实现一遍。如果扩展的东西越多后果将不堪设想。于是为了解决这个问题这时候就需要用到桥接模式了。
所谓桥接模式就是把不同维度的模块之间进行分离保持各自的独立性然后再把这些模块进行桥接。这样子即使更改了哪个模块也不会受到影响。
不同维度模块的主要分离为抽象化和实现化进行分离 抽象化抽象化和修正抽象化。抽象化派生给修正抽象化 实现化实现化和具体实现化。实现化派生给具体实现化 关系实现化服务于抽象化。 以下将会解释这个概念。
特点 将抽象化与实现化进行脱耦也就是分离使得他们两个互相独立不会影响到彼此。
结构
抽象化接口Abstraction定义高层模块的接口。比如有设置形状大小等的抽象方法。作为形状的基类接口
修正抽象化类(Refined Abstraction)扩展抽象化改变或实现抽象化的接口。比如扩展为矩形类、三角形类并实现大小的接口作为 Abstraction 的派生类
实现化接口(Implementor)定义底层模块的接口。比如画笔粗细等的抽象方法作为画笔的基类接口
具体实现化类(Concrete Implementor)扩展实现化对实现化接口进行实现。比如扩展为铅笔类、毛笔类并实现粗细的接口作为 Implementor 的派生类
适合应用场景特点
可扩展性不同维度的模块都潜在可扩展性需要进行抽象化和实现化的分离。比如抽象化为形状接口、实现化为画笔接口服务与运用关系抽象化属于高层模块运用底层模块。实现化属于底层模块服务高层模块。比如画笔是为形状服务的桥接作用主要针对于不同维度的模块。修正抽象化通常包装一个实现化接口的派生实例。派生指的是具体实现化注重对象结构模型。把形状和画笔进行桥接 二、例子
需求
年底快到了公司将要组织一场年会活动以感谢大家这一年来为公司做出了贡献。老板做出决定需要在这场活动中有抽奖环节。于是领导把开发抽奖系统的任务交给你去做。具体需求是奖金设置一等奖有1名、二等奖有两名、三等奖有三名。第一轮被抽到的幸运者获得一等奖第二轮是二等奖第三轮是三等奖。后续可能还有安慰奖啥的领导和老板还在策划中。抽奖结束后需要公布中奖结果。目前参加成员有员工和员工家属。至于老板是否也参加抽奖环节还未定暂时先补个空到时候再做决定。
需求分析
中奖者员工、家属、老板未定和奖金一等奖、二等奖、三等奖、安慰奖啥的未定是属于不同维度的模块。奖金服务于中奖者作为底层模块而中奖者作为高层模块运用底层模块。但两者的定义互不影响。即修改中奖者不影响奖金的代码逻辑反之亦然。本次抽奖活动在于老板是否参与还未定以及奖金的类别后续在规划中都属于可扩展的功能需求。
1、定义实现化接口和具体实现化类
底层模块奖金
//Implementor实现化接口奖金interface IBonus{string getGift();}//ConcreteImplementor具体实现化类一等奖class OneBonus : IBonus{public string getGift(){return iPhone 15 Pro;}}//ConcreteImplementor具体实现化类二等奖class TwoBonus : IBonus{public string getGift(){return HUAWEI MatePad Pro 13.2;}}//ConcreteImplementor具体实现化类三等奖class ThreeBonus : IBonus{public string getGift(){return Xiaomi 14 Pro;}}//可能还存在安慰奖、参与奖啥的...
2、定义抽象化接口和修正抽象化类
高层模块中奖者
//Abstraction抽象化接口中奖者interface ILucker{string Name { get; }void showResult();}//Refined Abstraction修正抽象化类员工中奖者class LuckyStaff : ILucker{private IBonus iBonus;private string _name;public string Name { get { return _name; } }public LuckyStaff(string name,IBonus iBonus){this.iBonus iBonus;_name name;}public void showResult(){Console.WriteLine(恭喜 {0}\t 获得一部 {1} 手机 !, Name, iBonus.getGift());}}//Refined Abstraction修正抽象化类可扩展员工家属中奖者class LuckyFamilyMember :ILucker{private IBonus iBonus;private string _name;public string Name { get { return _name; } }public LuckyFamilyMember(string name, IBonus iBonus){this.iBonus iBonus;_name name;}public void showResult(){Console.WriteLine(恭喜 {0}家属\t 获得一部 {1} 手机 !, Name, iBonus.getGift());}}
3、主程序抽奖名单公布结果
class Program{static void Main(string[] args){OneBonus oneBounds new OneBonus();TwoBonus twoBonus new TwoBonus();ThreeBonus threeBnus new ThreeBonus();//抽奖名单...ListILucker lucker new ListILucker(){//第一轮抽奖new LuckyFamilyMember(CRongQ,oneBounds),//第二轮抽奖new LuckyStaff(张三,twoBonus),new LuckyStaff(小蓝,twoBonus),//第三轮抽奖new LuckyStaff(小红,threeBnus),new LuckyFamilyMember(李四,threeBnus),new LuckyStaff(赵五,threeBnus)};Console.WriteLine(抽奖结果\n);foreach (var item in lucker){item.showResult();}Console.ReadLine();}}