前言
适配器模式可以在不改变目标代码的情况下,通过引入适配类来给目标类扩展功能。桥接模式也是一种结构型模式。
以下没有更形象生动的介绍,结合平时所写代码进行理解为佳
目录
一、定义
将抽象和实现解耦,使得两者可以独立变化。这里的抽象和实现可以理解为抽象实体和抽象出行为
二、模式原理分析
打个比方,你有一家房地产公司,后面增加了新业务,成立了新的公司,专门快速山寨其它行业爆品
//抽象公司 公司共有属性
public abstract class Corp{
//生产
protected abstract void produce();
//卖产品
protected abstract void sell();
//公司开始运营挣钱
public void run(){
this.produce();
this.sell();
}
}
//你的房地产公司
public class HouseCorp extends Corp(){
protected void produce(){
System.out.println("工人替老板盖房子并给工人发工资");
}
protected void sell(){
System.out.println("工人拿到工资后,再借钱向老板买房子");
}
}
//新开的山寨服装公司
public class ClothesCorp extends Corp{
protected void produce(){
System.out.println("回收旧衣服,加以利用");
}
protected void sell(){
System.out.println("旧衣服到底卖不卖");
}
}
//场景类
public class Client{
public static void main(String[] args){
HouseCorp houseCrop = new HouseCorp();
houseCorp.run();
ClothesCorp clothesCorp = new ClothesCorp();
clothesCorp.run();
}
}
复制代码
如果山寨衣服的公司不想生产衣服了,怎么办?删除这个类,然后新建一个具有新产品的类吗?这样的代码改动,也就是新建一个类继承Corp
,你可以接受吗?前期是可以的,后期如果变化快,那岂不是场景类中需要大量修改代码。我们可以转变思维,抽象出产品类,每次你只要指定生产哪个产品就可以了,只要符合规范。
现利用桥接模式改为
//抽象产品类
public abstract class Product{
public abstract void beProducted();
public abstract void beSelled();
}
//房子 产品
public class House extends Product{
public void beProducted(){
System.out.println("生产房子");
}
public void beSelled(){
System.out.println("卖房子");
}
}
//山寨衣服 产品
public class Clothes extends Product{
public void beProducted(){
System.out.println("生产衣服");
}
public void beSelled(){
System.out.println("卖衣服");
}
}
//抽象公司
public abstract class Corp{
private Product product;
public Corp(Product product){
this.product = product;
}
public void run(){
//生产产品
this.product.beProducted();
//卖产品
this.product.beSelled();
}
}
//房产公司
public class HouseCorp extends Corp{
public HouseCorp(House house){
super(house);
}
public void run(){
super.run();
}
}
//山寨公司
public class ShanZhaiCorp extend Corp{
public ShanZhaiCorp(Product product){
super(product);
}
public void run(){
super.run();
}
}
//场景类
public class Client{
public static void main(String[] args){
House house = new House();
HouseCorp houseCorp = new HouseCorp(house);
houseCorp.run();
ShanZhaiCorp shanZhaiCorp = new ShanZhaiCorp(new Clothes());
shanZhaiCorp.run();
}
}
复制代码
这里的构造函数,主要是为了提醒子类,你必须做这项工作。以后每次山寨产品,扩展,只需要增加公司,继承Corp
类,增加对应产品类。
对应于抽象和实现分离,这里Product
可以认为是实现化,Corp
可以认为是抽象化,Product
的子类 与ShanZhaiCorp
已经分离了。山寨公司ShanZhaiCorp
实现类,包含了抽象行为类Product
以及实现了抽象行为run
。
三、使用场景
-
不希望使用继承的场景
-
接口或抽象类不稳定的场景
-
基于消息驱动的场景。 虽然消息的行为比较统一,主要包括发送、接收、处理和回执,但其实具体客户端的实现通常却各不相同,比如,手机短信、邮件消息、QQ 消息、微信消息等。
-
拆分复杂的类对象时。 当一个类中包含大量对象和方法时,既不方便阅读,也不方便修改。
-
需要在运行时切换不同实现方法时。 比如,通过门面模式调用外部 RPC 服务。
-
重用性要求高的场景。设计的颗粒度越细,重用的可能性就越大,采用继承的方式受父类的限制。
四、优点
-
抽象和实现分离
- 解决了继承的缺点,实现可以不受抽象的约束
-
优秀的扩充能力
- 增加
Product
的实现,可以把变化缩减至最小
- 增加
-
实现细节对客户透明
- 不用关心细节如何,只需要完成产品实现
五、缺点
-
增加了维护成本,用组合和聚合关系不像继承关系那样容易找到对象之间的调用关系,稍不注意就会影响到其他对象
-
增加了设计难度,桥接模式更重视聚合而非继承关系,需要建立更多的抽象层
-
性能下降,组合或者聚合关系,简化理解的同时,调用对象变多了