设计模式—桥接模式

前言

这里以电视遥控器为例子引出桥接模式,首先每个牌子的电视都有一个遥控器,可以设计吧遥控器作为一个抽象类,抽象类中提供遥控器的所有实现,其他具体电视品牌的遥控器都继承这个抽象类

 

这样的实现使得每个不同型号的电视都有自己的遥控器实现,这样的设计对于电视剧品牌的改变可以很好的应对,只要添加一个派生类就可以了。但是随着时间的推移,用户需要改变遥控器的功能,如:用户可能需要添加一个返回上个台的功能,这是就需要修改抽象类了,这样就违反了设计原则,如果用户同时改变电视剧的品牌型号和遥控器功能时,此时的设计就更麻烦了,而使用桥接模式可以很好的解决问题

 

桥接模式介绍

桥接模式即将抽象部分与实现部分脱耦,使它们可以独立改变。对于上面的问题,抽象化也就是RemoteControl类,实现部分就是on(),off(),nextchannel(),这样的方法。上面设计中抽象化和实现部分在一起,桥接模式的目的就是使两者分开,我们把实现部分的变化封装到另外一个类中,这样一个思路就是桥接模式的实现

1)实际例子

抽象化部分代码

 

    //注释:里面方法定义成virtual 以方便如果有类继承此类时可以任意重写其中的方法/// <summary>/// 抽象概念中的遥控器,扮演抽象化角色/// </summary>public class RemoteControl{private TV implementor;public TV Implementor{get { return implementor; }set { implementor = value; }}//public virtual void MdadCity()//{//    implementor.MadeCity();//}/// <summary>/// 开电视机,这里抽象类中不再提供实现了,而是调用实现类中的实现/// </summary>public virtual void On(){implementor.On();}/// <summary>/// 关电视机/// </summary>public virtual void Off(){implementor.Off();}/// <summary>/// 换频道/// </summary>public virtual void RuneChannel(){implementor.RuneChannel();}}/// <summary>/// 具体遥控器/// </summary>public class ConcreteRemote : RemoteControl{public override void RuneChannel(){Console.WriteLine("---------------------");base.RuneChannel();Console.WriteLine("---------------------");}}

 

 实现方法的部分代码我们用另外一个抽象类TV封装了遥控器的功能变化,具体实现交给具体型号电视去完成

  //注释:定义成抽象类,如果有公共的方法可以在该抽象类中进行实习,如果是接口的话有些公共的方法就不能复用了/// <summary>/// 电视机,提供抽象方法/// </summary>public abstract class TV{//public void MadeCity()//{//    Console.WriteLine("made in china");//}public abstract void On();public abstract void Off();public abstract void RuneChannel();}/// <summary>/// 长虹牌电视机,重写基类的抽象方法/// 提供具体的实现/// </summary>public class ChangHong : TV{public override void On(){Console.WriteLine("长虹牌电视机打开");}public override void Off(){Console.WriteLine("长虹牌电视机关闭");}public override void RuneChannel(){Console.WriteLine("长虹牌电视机换台");}}/// <summary>/// 三星牌电视机,重写基类的抽象方法/// </summary>public class SanXing : TV{public override void On(){Console.WriteLine("三星牌电视机打开");}public override void Off(){Console.WriteLine("三星牌电视机关闭");}public override void RuneChannel(){Console.WriteLine("三星牌电视机换台");}}

 客户端调用时

 static void Main1(string[] args){RemoteControl remoteControl = new ConcreteRemote();remoteControl.Implementor = new ChangHong();remoteControl.On();remoteControl.RuneChannel();remoteControl.Off();Console.WriteLine();remoteControl.Implementor = new SanXing();remoteControl.On();remoteControl.RuneChannel();remoteControl.Off();Console.Read();}

 运行结果:

上面打代码实现中,遥控器的实现方法不再遥控器抽象类中实现了,而是把实现部分用另一个电视类去封装,遥控器中只包含电视剧类的引用。通过桥接模式,我们把抽象化和实现部分代码分离,这样就可以很好的应对这两个方面的变化了。

 

2)桥接模式介绍

3)桥接模式分析

优点:抽象接口与其实现解耦

         抽象和实现可以独立扩展,不会影响对方

缺点:增加了系统的复杂度

4)使用场景

如果一个系统需要在构件的抽象化角色和具体化角色之间添加更多的灵活性,避免在两个层次之间建立静态的联系

设计要求实现化角色的任何改变不应担影响客户端,或者实现化角色的改变对客户端是完全透明的

需要跨越多个平台的图形和窗口系统上

一个类存在两个对立变化的纬度,且两个纬度都需要进行扩展

5)实际例子

桥接模式经常用于具体的系统开发中,对于三层架构中就应用了桥接模式,三层架构中的业务逻辑层bll中通过桥接模式与数据库操作层解耦,其实现方式就是在bll层中引用了dal层中一个引用,这样数据操作的实现可以在不改变客户端代码的情况下动态进行更换了

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace ConsoleApplication1
{// BLL 层public class BusinessObject{private DataAccess dataAccess;private string city;public BusinessObject(string city){this.city = city;}public DataAccess DataAccess{get { return dataAccess; }set { dataAccess = value; }}public virtual void Add(string name){dataAccess.AddRecord(name);}public virtual void Delete(string name){dataAccess.DeleteRecord(name);}public virtual void Update(string name){dataAccess.UpdateRecord(name);}public virtual string Get(int index){return dataAccess.GetRecord(index);}public virtual void ShowAll(){Console.WriteLine();Console.WriteLine("{0}的顾客有:", city);dataAccess.ShowAllRecords();}}public class CustomersBusinessObject : BusinessObject{public CustomersBusinessObject(string city) : base(city) { }public override void ShowAll(){Console.WriteLine("----------");base.ShowAll();Console.WriteLine("___________");}}/// <summary>/// 相当于三层架构中数据访问层(DAL)/// </summary>public abstract class DataAccess{// 对记录的增删改查操作public abstract void AddRecord(string name);public abstract void DeleteRecord(string name);public abstract void UpdateRecord(string name);public abstract string GetRecord(int index);public abstract void ShowAllRecords();}public class CustomersDataAccess : DataAccess{private List<string> customers = new List<string>();public CustomersDataAccess(){customers.Add("Learning Hard");customers.Add("张三");customers.Add("李四");customers.Add("王五");}public override void AddRecord(string name){customers.Add(name);}public override void DeleteRecord(string name){customers.Remove(name);}public override void UpdateRecord(string updatename){customers[0] = updatename;}public override string GetRecord(int index){return customers[index];}public override void ShowAllRecords(){foreach (string name in customers){Console.WriteLine(" " + name);}}}
}

 

 客户端调用:

 // 类似Web应用程序static void Main(string[] args){BusinessObject customers = new CustomersBusinessObject("shanghai");customers.DataAccess = new CustomersDataAccess();customers.Add("小六");Console.WriteLine("增加了一位成员的结果:");customers.ShowAll();customers.Delete("王五");Console.WriteLine("删除了一位成员的结果:");customers.ShowAll();customers.Update("Learning_Hard");Console.WriteLine("更新了一位成员的结果:");customers.ShowAll();Console.Read();}

 运行结果:

 

转载于:https://www.cnblogs.com/xishuqingchun/p/5012074.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/471354.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode 2125. 银行中的激光束数量

文章目录1. 题目2. 解题1. 题目 银行内部的防盗安全装置已经激活。 给你一个下标从 0 开始的二进制字符串数组 bank &#xff0c;表示银行的平面图&#xff0c;这是一个大小为 m x n 的二维矩阵。 bank[i] 表示第 i 行的设备分布&#xff0c;由若干 ‘0’ 和若干 ‘1’ 组成。…

LeetCode 2126. 摧毁小行星(贪心)

文章目录1. 题目2. 解题1. 题目 给你一个整数 mass &#xff0c;它表示一颗行星的初始质量。 再给你一个整数数组 asteroids &#xff0c;其中 asteroids[i] 是第 i 颗小行星的质量。 你可以按 任意顺序 重新安排小行星的顺序&#xff0c;然后让行星跟它们发生碰撞。如果行星…

bzoj:2018 [Usaco2009 Nov]农场技艺大赛

Description Input 第1行&#xff1a;10个空格分开的整数: N, a, b, c, d, e, f, g, h, M Output 第1行&#xff1a;满足总重量最轻&#xff0c;且用度之和最大的N头奶牛的总体重模M后的余数。 Sample Input 2 0 1 5 55555555 0 1 0 55555555 55555555Sample Output 51HINT 样例…

LeetCode 2129. 将标题首字母大写

文章目录1. 题目2. 解题1. 题目 给你一个字符串 title &#xff0c;它由单个空格连接一个或多个单词组成&#xff0c;每个单词都只包含英文字母。请你按以下规则将每个单词的首字母 大写 &#xff1a; 如果单词的长度为 1 或者 2 &#xff0c;所有字母变成小写。否则&#xf…

LeetCode 2130. 链表最大孪生和(链表快慢指针+反转链表+双指针)

文章目录1. 题目2. 解题1. 题目 在一个大小为 n 且 n 为 偶数 的链表中&#xff0c;对于 0 < i < (n / 2) - 1 的 i &#xff0c;第 i 个节点&#xff08;下标从 0 开始&#xff09;的孪生节点为第 (n-1-i) 个节点 。 比方说&#xff0c;n 4 那么节点 0 是节点 3 的孪…

Splay初步【bzoj1503】

做了一道水题&#xff0c;把bzoj1503用Splay重新写了一下。 1 #include <bits/stdc.h>2 #define rep(i, a, b) for (int i a; i < b; i)3 #define REP(i, a, b) for (int i a; i < b; i)4 #define drep(i, a, b) for (int i a; i > b; i--)5 #define mp make…

原生html5时间组件,JFinal遇到了原生Html5时间组件格式转换问题怎么处理?

今天JBolt种子用户群里有人提问&#xff0c;JFinal针对原生Html5的日期时间选择组件的格式转换支持有问题&#xff0c;报错。于是我在JBolt的Demo中加入了这些去测试一下&#xff0c;这里使用的都是原生Html组件。Input type“text”默认就是一个简单的单行文本输入框。如果修改…

LeetCode 2131. 连接两字母单词得到的最长回文串

文章目录1. 题目2. 解题1. 题目 给你一个字符串数组 words 。words 中每个元素都是一个包含 两个 小写英文字母的单词。 请你从 words 中选择一些元素并按 任意顺序 连接它们&#xff0c;并得到一个 尽可能长的回文串 。每个元素 至多 只能使用一次。 请你返回你能得到的最长…

LeetCode 2132. 用邮票贴满网格图(DP/二维差分)

文章目录1. 题目2. 解题1. 题目 给你一个 m x n 的二进制矩阵 grid &#xff0c;每个格子要么为 0 &#xff08;空&#xff09;要么为 1 &#xff08;被占据&#xff09;。 给你邮票的尺寸为 stampHeight x stampWidth 。我们想将邮票贴进二进制矩阵中&#xff0c;且满足以下…

blue html中转换,BlueFox Free PDF to HTML Converter(PDF文件转换软件)

BlueFox Free PDF to HTML Converter是一款pdf文件转换软件&#xff0c;能直接查看PDF文件和对PDF文件进行编辑&#xff0c;支持批量进行转换&#xff0c;使用非常方便&#xff0c;操作简单&#xff0c;有需要可以下载。软件特色通过将PDF转换为HTML网页&#xff0c;您的网站访…

二、前端pink老师的CSS定位学习笔记(超详细,简单易懂)

定位(position) 1. CSS 布局的三种机制 网页布局的核心 —— 就是用 CSS 来摆放盒子位置。 CSS 提供了 3 种机制来设置盒子的摆放位置&#xff0c;分别是普通流、浮动和定位&#xff0c;其中&#xff1a; 普通流&#xff08;标准流&#xff09; 浮动 让盒子从普通流中浮起来 …

LeetCode 2133. 检查是否每一行每一列都包含全部整数

文章目录1. 题目2. 解题1. 题目 对一个大小为 n x n 的矩阵而言&#xff0c;如果其每一行和每一列都包含从 1 到 n 的 全部 整数&#xff08;含 1 和 n&#xff09;&#xff0c;则认为该矩阵是一个 有效 矩阵。 给你一个大小为 n x n 的整数矩阵 matrix &#xff0c;请你判断…

上传图片自动加水印html,html5上传多个文件并添加水印 实例源码

【实例简介】【实例截图】【核心代码】html5上传多个文件并添加水印body{font-size:12px;}a{text-decoration:none;}a,a:after{-webkit-transition:all 0.3s;-moz-transition:all 0.3s;transition:all 0.3s;}a.btn i{display:block;width:100%;height:100%;position:relative;z…

LoadRunner培训初级教程

一 LoadRunner简介 1.1 Loadrunner介绍 LoadRunner 是 HP Mercury Interactive用来测试应用程序性能的工具 LoadRunner 通过模拟一个多用户并行工作的环境来对应用程序进行负载测试。通过使用最少的硬件资源&#xff0c;这些虚拟用户提供一致的、可重复并可度量的负载&#xf…

android model 设计,Android model层设计

model层在开发app的过程中&#xff0c;不管是使用了mvp还是mvc甚至mvvm模式,model层的设计基本都是一样的&#xff0c;model层可以被称为数据层&#xff0c;它的主要任务就是为上层提供各种的数据服务&#xff0c;上层完全不需要关心这些数据是来自网络&#xff0c;还是内存&am…

LeetCode 2134. 最少交换次数来组合所有的 1 II(数组*2 + 滑动窗口)

文章目录1. 题目2. 解题1. 题目 交换 定义为选中一个数组中的两个 互不相同 的位置并交换二者的值。 环形 数组是一个数组&#xff0c;可以认为 第一个 元素和 最后一个 元素 相邻 。 给你一个 二进制环形 数组 nums &#xff0c;返回在 任意位置 将数组中的所有 1 聚集在一…

四、pink老师的学习笔记——元素的显示与隐藏

1. 元素的显示与隐藏 目的 让一个元素在页面中消失或者显示出来 场景 类似网站广告&#xff0c;当我们点击关闭就不见了&#xff0c;但是我们重新刷新页面&#xff0c;会重新出现&#xff01; 1.1 display 显示&#xff08;重点&#xff09; display 设置或检索对象是否及如…

SpringMVC详解

来源&#xff1a;Sunnier&#xff08;http://www.admin10000.com/document/6436.html&#xff09; 一、SpringMVC基础入门&#xff0c;创建一个HelloWorld程序 1.首先&#xff0c;导入SpringMVC需要的jar包。 2.添加Web.xml配置文件中关于SpringMVC的配置 12345678910111213141…

LeetCode 2135. 统计追加字母可以获得的单词数(位运算+哈希)

文章目录1. 题目2. 解题1. 题目 给你两个下标从 0 开始的字符串数组 startWords 和 targetWords 。每个字符串都仅由 小写英文字母 组成。 对于 targetWords 中的每个字符串&#xff0c;检查是否能够从 startWords 中选出一个字符串&#xff0c;执行一次 转换操作 &#xff0…

五、pink老师的学习笔记——CSS精灵技术(sprite)

5. CSS精灵技术&#xff08;sprite) 重点 5.1 为什么需要精灵技术 图所示为网页的请求原理图&#xff0c;当用户访问一个网站时&#xff0c;需要向服务器发送请求&#xff0c;网页上的每张图像都要经过一次请求才能展现给用户。 然而&#xff0c;一个网页中往往会应用很多小的…