设计模式之桥接模式

一、桥接模式:如果软件系统中某个类存在多个独立变化的维度,我们可以将这多个维度分离出来,使这些维度可以独立扩展,比如一个表示教师的类 ,他原本包含教师资格级别和所教学科这个两个维度,如果我们抽象出一个教师类,然后要实现各个级别、各个学科的教师的话 ,就需要实现教师资格级别数量(M)和教学学科数量(N)的乘积M*N个实现类,而如果我们 将教师资格级别、教学学科从教师类中抽象出来,我们只需要实现这两个抽象的所有实现类(M个教师资格级别实现类、N个教学学科实现类 ),然后在教师类中使用组合模式方式去引用这两类实现类,则只需要M+N个实现类就可以满足需求,客户端需要什么样的实现类由它自己指定,这样既减少了实现类的数量,又增强了程序的灵活性,这种设计模式我们称之为桥接模式。

二、实现思路 :将一个类中多个独立变化的纬度分别抽象出一个抽象类,把具体的变化情况作为其对应抽象的实现类,在类中保留对这些抽象类的引用,由客户端指定其具体的实现类以满足不同的需求。

三、代码举例: 

A、多重继承模式下的类代码:

1、抽象教师类:

namespace Bridge.继承模式
{
    public abstract class Teacher
    {
        public abstract string TeachSubject { get; set; }//教学学科
        public abstract string SchoolRank { get; set; }//教学学校等级
        public abstract void BeginClass();//开始上课

    }
}

 2、实现类:

namespace Bridge.继承模式
{
    /// <summary>
    /// 高中语文老师
    /// </summary>
    public class HighchoolChineseTeacher : Teacher
    {
        public HighchoolChineseTeacher()
        {
            this.TeachSubject = "语文";
            this.SchoolRank = "高中";
        }
        public override string TeachSubject { get ; set; }
        public override string SchoolRank { get; set; }
        public override void BeginClass()
        {
            Console.WriteLine(this.SchoolRank+ "教师级别的"+ this.TeachSubject + "老师开始上" + this.TeachSubject+"课.....");
        }
    }
}

 

namespace Bridge.继承模式
{
    /// <summary>
    /// 高中英语老师
    /// </summary>
    public class HighchoolEnglishTeacher : Teacher
    {

        public HighchoolEnglishTeacher()
        {
            this.TeachSubject = "英语";
            this.SchoolRank = "高中";
        }
        public override string TeachSubject { get; set; }
        public override string SchoolRank { get; set; }
        public override void BeginClass()
        {
            Console.WriteLine(this.SchoolRank + "教师级别的" + this.TeachSubject + "老师开始上" + this.TeachSubject + "课.....");
        }
    }
}

 

namespace Bridge.继承模式
{
    /// <summary>
    /// 初中语文老师
    /// </summary>
    public class MiddlechoolChineseTeacher : Teacher
    {

        public MiddlechoolChineseTeacher()
        {
            this.TeachSubject = "语文";
            this.SchoolRank = "初中";
        }
        public override string TeachSubject { get; set; }
        public override string SchoolRank { get; set; }
        public override void BeginClass()
        {
            Console.WriteLine(this.SchoolRank + "教师级别的" + this.TeachSubject + "老师开始上" + this.TeachSubject + "课.....");
        }
    }
}

 

namespace Bridge.继承模式
{
    /// <summary>
    /// 高初中英语老师
    /// </summary>
    public class MiddlechoolEnglishTeacher : Teacher
    {
        public MiddlechoolEnglishTeacher()
        {
            this.TeachSubject = "英语";
            this.SchoolRank = "初中";
        }
        public override string TeachSubject { get; set; }
        public override string SchoolRank { get; set; }
        public override void BeginClass()
        {
            Console.WriteLine(this.SchoolRank + "教师级别的" + this.TeachSubject + "老师开始上" + this.TeachSubject + "课.....");
        }
    }
}

 

namespace Bridge.继承模式
{
    /// <summary>
    /// 小学语文老师
    /// </summary>
    public class PrimaryschoolChineseTeacher : Teacher
    {
        public PrimaryschoolChineseTeacher()
        {
            this.TeachSubject = "语文";
            this.SchoolRank = "小学";
        }
        public override string TeachSubject { get; set; }
        public override string SchoolRank { get; set; }
        public override void BeginClass()
        {
            Console.WriteLine(this.SchoolRank + "教师级别的" + this.TeachSubject + "老师开始上" + this.TeachSubject + "课.....");
        }
    }
}

 

namespace Bridge.继承模式
{
    /// <summary>
    ///小学英语教师
    /// </summary>
    public class PrimaryschoolEnglishTeacher : Teacher
    {
        public PrimaryschoolEnglishTeacher()
        {
            this.TeachSubject = "英语";
            this.SchoolRank = "小学";
        }
        public override string TeachSubject { get; set; }
        public override string SchoolRank { get; set; }
        public override void BeginClass()
        {
            Console.WriteLine(this.SchoolRank + "教师级别的" + this.TeachSubject + "老师开始上" + this.TeachSubject + "课.....");
        }
    }
}

 B、 桥接模式下的类代码:

 1、学科接口:

namespace Bridge.桥接模式
{
    public interface ISubject
    {
        string Subject();
    }
}

 2、教学等级接口:

namespace Bridge.桥接模式
{
    public interface ISchool
    {
        String  Rank();//学校等级
    }
}

 3、学科接口实现类:

namespace Bridge.桥接模式
{
    public class ChineseSubject : ISubject
    {
        public string Subject()
        {
            return "语文";
        }
    }
}

namespace Bridge.桥接模式
{
    public class EnglishSubject : ISubject
    {
        public string Subject()
        {
            return "英语";
        }
    }
}

 4、教学等级接口实现类:

namespace Bridge.桥接模式
{
    public class Middlechool : ISchool
    {
        public string Rank()
        {
            return "中学";
        }
    }
}

namespace Bridge.桥接模式
{
    class Primaryschool:ISchool
    {
        public string Rank()
        {
            return "小学";
        }
    }
}

 5、Teacher类:

namespace Bridge.桥接模式
{
   public  class Teacher
    {
        public ISchool _school = null;
        public ISubject _subject = null;
        public void BeginClass()
        {
            Console.WriteLine(this._school.Rank() + "教师级别的" + this._subject.Subject() + "老师开始上" + this._subject.Subject() + "课.....");
        }
    }
}

 6、客户端调用:

{
                //桥接模式与继承模式的对比:
                Bridge.继承模式.Teacher teacher0 = new Bridge.继承模式.PrimaryschoolChineseTeacher();
                teacher0.BeginClass();
                Bridge.继承模式.Teacher teacher1 = new Bridge.继承模式.MiddlechoolEnglishTeacher();
                teacher1.BeginClass();
                Console.WriteLine("..........以下是桥接模式代码...................");
                //如果按照以上的继承方式进行设计,假如现在教师资格固定为小学、初中、高中、大学这几类,客户端分别需要这几个资格的生物老师各一名,那么就需要同时增加4个生物老师实现类。
                //如果还需要这几个资格的化学老师各一名,则又需要4个化学老师实现类,以此类推,政理化史地生语数英这9大学学科都分别需要一名老师的话,那么老师实现类的数量为9*4=32名。
                //万一客户端还需要研究生导师、博士生导师等教师资格的老师呢?那全部计算下来需要实现类的数量为6*9=54个Teacher实现类,这造成了实现类爆炸性的增加,这下子这程序还怎么往下写?
                //有没有办法能够让扩展时减少实现类的数量?答案是使用桥接模式。
                Bridge.桥接模式.Teacher techer2 = new Bridge.桥接模式.Teacher();
                techer2._school = new Bridge.桥接模式.HighSchool();
                techer2._subject = new Bridge.桥接模式.EnglishSubject();
                techer2.BeginClass();

                Bridge.桥接模式.Teacher techer3 = new Bridge.桥接模式.Teacher();
                techer3._school = new Bridge.桥接模式.Middlechool();
                techer3._subject = new Bridge.桥接模式.ChineseSubject();
                techer3.BeginClass();
                //使用桥接模式将抽象和实现分离,使他们可以独立的变化:假如需要加入需要一组数学老师,我们只需要新增一个实现ISubject 接口的数学类,通过上端指定参数,就可以取得各个学校级别的数学老师
                //如果按照上面的继承模式,当我们需要新增一组数学老师时,就需要分别创建一个小学、初中、高中、大学的实现类对象。使用桥接模式,假如教师资格固定为小学、初中、高中、大学、研究生导师、博士生导师6类
                //学科为政理化史地生语数英这9大学学科,则需要实现类数量为6个ISchool实现类+9个ISubject实现类=15个,比继承模式中54个少了几倍。,
                //在以上两种模式中,如果还需要区分老师性别,继承模式中实现类的数量为2*6*9=108个,桥接模式中实现类数量为2+6+9=17个。两种模式相比,桥接模式的优点就出来了。桥接模式也有使用起来比较
                //麻烦的缺点:继承模式只需要new一个实现类即可,而桥接模式需要多new几个实现类进行指定,对于客户端而言需要了解更多的细节。
                Console.ReadKey();
            }

 7、运行结果:

 四、桥接模式的优缺点及应用:该模式适用于一个类具有多维度变化的情况,易于扩展,使用灵活,但客户端需要了解更多的细节,使用较为麻烦。

posted @ 2019-01-24 17:24  我若安好,便是晴天  阅读(11)  评论(0编辑  收藏  举报