桥接模式从最初代码的一步步改进

桥接模式的动机:
由于某些类型的固有的实现逻辑,使得它们具有两个乃至多个变化的维度。
如何应对这种“多维度的变化”?如何利用面向对象技术使得类型可以轻松地沿着两个乃至多个方向变化,而不引入额外的复杂度?

场景描述:
● 手机都有通讯录和游戏功能,M品牌手机和N品牌手机都有通讯录的增删改查功能和游戏功能。可以有两种结构
结构1:
◇ 父亲是‘手机品牌’,下有‘手机品牌M’和‘手机品牌N’,每个子类下各有‘通讯录’和‘游戏’子类。
结构2:
◇ 父类时‘手机软件’,下有‘通讯录’和‘游戏’子类,每个子类下各有‘手机品牌M’和‘手机品牌N’。

结构1:

结构2:

● 在面向对象设计中,有一个很重要的设计原则:
合成/聚合复用原则。即优先使用对象合成/聚合,而不是类继承。
● 合成/聚合复用原则的好处是,优先使用对象的合成/聚合有助于保持每个类并封装,并集中在单个任务上。这样类和类继承层次会保持较小规模,并且不太可能增长为不可控制的庞然大物。

问题:
● Q:如果现在需要每个品牌都增加一个音乐播放功能,如何做?
● A:结构1要求在每个品牌的下面都增加一个子类;结构2要求在每个手机软件下面增加一个音乐播放子类,在这个子类下为每个品牌增加音乐播放功能。这两个子类的差别不大,但是因额为品牌不同,增加功能就不太容易。
● Q:现在又来了一家新的手机品牌‘S’,它也有游戏、通讯录、音乐播放功能,如何处理?
● A:那就得在增加‘手机品牌S’类和三个下属功能子类。
这就很麻烦了,如果还需要增加‘输入法’功能、‘拍照’功能,在增加‘L品牌’、‘L品牌’类非常困难。

● 上面的问题,需要用对象的职责,而不是结构来考虑问题。
● 实际上,‘游戏’、‘通讯录’、‘音乐播放’这些功能都是软件,让其分离与手机的耦合,就大大减少面对新需求时改动过大的不合理情况。
● 应该有个‘手机品牌’抽象类和‘手机软件’抽象类,让不同的品牌和功能都分别继承于它们,这样要增加新的品牌或新的功能就不用影响其它类了。

结构图:

       手机品牌和手机软件之间的关系是手机品牌包含有手机软件,但软件并不是品牌的一部分,所以它们之间是聚合关系。

基本代码:

//手机软件
abstract class HandsetSoft
{
	public abstract void Run();
}
//手机品牌
abstract class HandsetBrand
{
	protected HandsetSoft soft;
	//设置手机软件
	public void SetHandsetSoft(HandsetSoft soft)
	{
		this.soft = soft;
	}
	//运行
	public abstract void Run();
}
class HandsetBrandM extends HandsetBrand//手机品牌M
{
	public void Run()
	{
		System.out.println("M Brand");
		soft.Run();
	}
}
class HandsetBrandN extends HandsetBrand//手机品牌N
{
	public void Run()
	{
		System.out.println("N Brand");
		soft.Run();
	}
}
class HandsetGame extends HandsetSoft//手机游戏
{
	public void Run()
	{System.out.println("运行手机游戏");}
}
class AddressList extends HandsetSoft//手机通讯录
{
	public void Run()
	{System.out.println("运行手机通讯录");}
}
class Mp3 extends HandsetSoft//手机mp3
{
	public void Run()
	{System.out.println("运行手机mp3");}
}

客户端:

public class CellPhonePattern
{
	public static void main(String[] args)
	{
		HandsetBrand ab;
		ab = new HandsetBrandN();
		ab.SetHandsetSoft(new HandsetGame()); ab.Run();
		ab.SetHandsetSoft(new AddressList()); ab.Run();
		
		ab = new HandsetBrandM();
		ab.SetHandsetSoft(new HandsetGame()); ab.Run();
		ab.SetHandsetSoft(new AddressList()); ab.Run();
		ab.SetHandsetSoft(new Mp3()); ab.Run();
	}
}

解决问题:
● 如果要增加一个功能,比如拍照功能,在手机软件部分增加手机拍照子类。类的个数增加也只是一个。不会影响其他任何类。
● 如果要增加S品牌,在手机品牌部分增加一个品牌子类就可以了。个数也是一个,不会影响其他类。

代码实现:
在手机软件部分添加一个手机拍照类

//手机拍照
class photo extends HandsetSoft
{
	public void Run()
	{System.out.println("运行手机牌照");}
}

在手机品牌部分添加一个手机品牌S类

//手机品牌S
class HandsetBrantS extends HandsetBrand
{
	public void Run()
	{
		System.out.println("S Brand");
		soft.Run();
	}
}

客户端增加:

ab = new HandsetBrandS();
ab.SetHandsetSoft(new HandsetGame()); ab.Run();
ab.SetHandsetSoft(new AddressList()); ab.Run();
ab.SetHandsetSoft(new Mp3());         ab.Run();
ab.SetHandsetSoft(new photo());       ab.Run();

       这样的设计符合开放-封闭原则,不会修改原来的代码,而只是扩展类就行了。
       合成/聚合复用原则,优先使用对象的合成或聚合,而不是类继承。

桥接模式:


● 可以看出,这个系统含有两个等级结构:
    ◇ 由抽象化角色和提炼抽象化角色组成的抽象化等级结构。
    ◇ 由实现化角色和两个具体实现化角色所组成的实现化等级结构。

基本代码:

//Implementor类
abstract class Implementor
{
	public abstract void Operation();
}
public class ConcreteImplementorA extends Implementor
{
	public void Operation()
	{
		System.out.println("具体实现A的方法执行");
	}
}
public class ConcreteImplementorB extends Implementor
{
	public void Operation()
	{
		System.out.println("具体实现B的方法执行");
	}
}
//Abstraction类
public class Sbstraction
{
	protected Implementor implementor;
	public void SetImplementor(Implementor implementor)
	{this.implementor = implementor;}
	public void Operation()
	{implementor.Operation();}
}
//RefinedAbstraction类
public class RefinedAbstraction extends Abstraction
{
	public void Operation()
	{
		implementor.Operation();
	}
}

//客户端调用代码
public class client
{
	public static void main(String[] args)
	{
		Abstraction ab = new RefinedAbstraction();
		
		ab.SetImplementor(new ConcreteImplementorA());
		ab.Operation();
		
		ab.SetImplementor(new ConcreteImplementorB());
		ab.Operation();
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
桥接模式(Bridge Pattern)是一种结构型设计模式,它将抽象部分与实现部分分离,使它们可以独立变化。下面是一个简单的 Java 代码示例: ``` // 定义实现部分的接口 interface DrawAPI { public void drawCircle(int radius, int x, int y); } // 定义具体实现部分的类 class RedCircle implements DrawAPI { public void drawCircle(int radius, int x, int y) { System.out.println("Drawing Circle[ color: red, radius: " + radius + ", x: " + x + ", y: " + y + "]"); } } class GreenCircle implements DrawAPI { public void drawCircle(int radius, int x, int y) { System.out.println("Drawing Circle[ color: green, radius: " + radius + ", x: " + x + ", y: " + y + "]"); } } // 定义抽象部分的类,并包含一个指向实现部分的引用 abstract class Shape { protected DrawAPI drawAPI; protected Shape(DrawAPI drawAPI){ this.drawAPI = drawAPI; } public abstract void draw(); } // 定义具体抽象部分的类 class Circle extends Shape { private int x, y, radius; public Circle(int x, int y, int radius, DrawAPI drawAPI) { super(drawAPI); this.x = x; this.y = y; this.radius = radius; } public void draw() { drawAPI.drawCircle(radius,x,y); } } // 测试代码 public class BridgePatternDemo { public static void main(String[] args) { Shape redCircle = new Circle(100,100, 10, new RedCircle()); Shape greenCircle = new Circle(100,100, 10, new GreenCircle()); redCircle.draw(); greenCircle.draw(); } } ``` 在上面的代码中,`DrawAPI` 接口定义了实现部分的方法,`RedCircle` 和 `GreenCircle` 是具体实现部分的类。`Shape` 是抽象部分的类,并包含一个指向实现部分的引用,在 `Circle` 中使用了 `drawAPI` 引用来调用 `DrawAPI` 接口的方法。在 `BridgePatternDemo` 类中,我们创建了一个红色圆和一个绿色圆,并分别调用了它们的 `draw()` 方法。 这个例子中,桥接模式的优点在于,我们可以轻松地增加新的实现部分类而不影响抽象部分类。例如,如果我们想添加蓝色圆形,我们只需要创建一个新的 `BlueCircle` 类并实现 `DrawAPI` 接口即可。这种灵活性使得桥接模式在一些复杂的系统中特别有用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值