[结构型(接口型模式)]the Bridge Pattern桥接模式
1.the intention of Bridge pattern 桥接模式的意图
Bridge pattern is to make interface separate with their respective concrete implementation.
桥接模式的意图是将抽象部分与他的实现部分相分离。
2.when to apply this pattern适用性
under the following conditions, we can apply to this pattern.一下情况之下我们可以适用Bridge模式
1. if we dont want there exist static binding relationship between the abstract class/interface and its implemantation.
如果我们不希望在它的抽象类和实现之间存在固定的绑定关系。
2. if we wanna that the abstract class and its respective inplementation can be expanded through generating subclass. Through applying Bridge pattern, we can combine different abstract class/interface with implementation, and expand them repectively.
抽象类及其实现都可以通过生成子类的方法加以扩充。这时Bridge模式使你可以对不同的抽象接口和实现进行组合,并分别对他们进行扩充。
3.对一个抽象的实现部分进行修改,但不会对客户产生影响,即客户的代码不必重新编译。
3. Bridge pattern implementation桥接模式实现
Bridge pattern 类图结构如下:
Bridge pattern 实现代码如下:
{
public Implementor _implementor;
public Implementor Implementor
{
get
{
return _implementor;
}
}
public abstract void AbsOperation();
}
public class ConcreteAbstraction : Abstraction
{
public override void AbsOperation()
{
if(_implementor!=null)
_implementor.Operation();
}
}
public interface Implementor
{
void Operation();
}
public class ConcreteImplementorA : Implementor
{
public void Operation()
{
Console.WriteLine("Concrete implementor A 's Operation");
}
}
public class ConcreteImplementorB : Implementor
{
public void Operation()
{
Console.WriteLine("Concrete implementor B 's Operation");
}
}
public class program
{
Abstraction abs = new ConcreteAbstraction();
abs._implementor = new ConcreteImplementorA();
abs.AbsOperation();
abs._implementor = new ConcreteImplementorB();
abs.AbsOperation();
}
运行结果如下:
Concrete implementor A's Operation
Concrete implementor B's Operation
5 Bridge模式开放-封闭性的讨论
[所谓开放-封闭性,是指一个模块在扩展性方面是开放的,而在更改性方面是封闭的]
1.假如后来因为需求改变。这时候实现ConconcreteImplementorA/B中的business regulation 发生改变。怎么办呢?因为我们采用的是Bridge pattern,很好解决。我们只需要对相应的concrete implementor进行修改即可,客户端代码不需要改变。
2.假设后来又有了新的ConcreteimplementorC?怎么办呢?很简单,只需要增加implement ConcreteImpletorC即可。其他地方毫无改变。
这就是Bridge 带来的好处
谨记Bridge模式的根本目的:将抽象部分与他的实现部分分离!!!
6. 应用举例
比如我们现在要开发一个计算收入的模块。我们都知道,收入由两部分组成=工资+奖金 - 个人所得税。现在假设有来自两个国家的人员,很显然,各个国家计算个人所得税的方法是不一样的。 假设,美国人的收入计算方法如下:
全职人员:工资*90%+奖金*80%
兼职人员:工资*80%
中国人的收入计算方法如下:
全职人员:工资*95%+奖金*75%
兼职人员:工资*80%
[说明:以上计算方法纯属虚构]
同时,如果美国人到了中国,就要按照中国的税收缴税来计算工资
现在,要设计一个模块,计算不同人的收入,同时要考虑到模块可能扩展应用到其他国家,比如日本,系统要易于扩充。
分析:
方案1:
设置一个基类People,然后派生出相应的类,比如在中国工作的全职中国人,在中国工作的兼职中国人,在中国工作的全职美国人,......等等,一共要派生6个类。my god! 这是M*N哦
方案2:
我们从中可以知道,计算工资这个动作不管是中国员工还是美国员工都是需要的。只不过,如果是中国员工,采取一套计算方法;如果是美国员工,又是另外一套计算方法。这不正是Bridge模式所描述的吗?下面我们用Bridge 模式实现这个模块。
这样,我们将问题分解成了M+N .so cool.
class diagram 如下:
code inplementation:
public interface Income
{
double Payment(double salary,double bonus);
}
public class Income_USA:Income
{
public double Payment(double salary, double bonus)
{
return salary * 0.9 + bonus * 0.8;
}
}
public class Income_CHN : Income
{
public double Payment(double salary, double bonus)
{
return salary * 0.95 + bonus * 0.75;
}
}
public class Income_PartTime : Income
{
public double Payment(double salary,double bonus)
{
return salary*0.8;
}
}
public abstract class Employee_Bridge
{
public Employee_Bridge(double salary, double bonus)
{
_salary = salary;
_bonus = bonus;
}
public Income Income
{
get
{
throw new System.NotImplementedException();
}
set
{
}
}
protected double _salary;
protected double _bonus;
public Income incomeFrom;
public abstract double GetPayment();
}
public class Employee_USA : Employee_Bridge
{
public Employee_USA(double salary, double bonus)
: base(salary, bonus)
{
}
public override double GetPayment()
{
return incomeFrom.Payment(_salary, _bonus);
}
}
public class Employee_CHN : Employee_Bridge
{
public Employee_CHN(double salary, double bonus)
: base(salary, bonus)
{
}
public override double GetPayment()
{
return incomeFrom.Payment(_salary, _bonus);
}
}
public class Program
{
Employee_Bridge hiron = new Employee_CHN(12000, 3000);
hiron.incomeFrom = new Income_USA();
Console.WriteLine(hiron.GetPayment());
Employee_Bridge winston = new Employee_USA(20000, 0);
winston.incomeFrom = new Income_PartTime();
Console.WriteLine(winston.GetPayment());
}
开放-封闭性测试:
1. 假如此时美国的税收政策发生改变,个人收入计算方法发生改变。这时候我们只需要对美国收入的计算模块算法作修改即可,客户端丝毫不会察觉任何改变。
2.如果模块要发不到日本,那么这时只需要在Income接口下派生出一个新的计算日本收入的类Income_JPN即可,非常易于扩展。 so cool :) understand?