真刀实枪之桥梁模式
- 从“I have Dream:”说起
- 每个热都有自己的梦想,但只要不是空想,理想是要靠今天的拼搏来实现的
- 现在假设字节的愿望可以自行设计与实现:那么来规划一下自己的事业吧
- 富翁进行时
- 房地产比较火,先来个房地产公司
- 服装业与人们生活息息相关,再来个服装公司
- 不要贪多,先把这两个公司先经营好再说
-
好了,富翁的公司已经规划好,现在来进行实现吧
- 类图
- 设计简单,但效益还不错!
-
代码来实现
-
Corp
package com.peng.ql; /** * @author kungfu~peng * @data 2017年12月6日 * @description */ public abstract class Corp { // 生产 protected abstract void produce(); // 销售 protected abstract void shell(); // 赚钱--模板方法 public void makeMoney() { this.produce(); this.shell(); } }
-
HouseCorp
package com.peng.ql; /** * @author kungfu~peng * @data 2017年12月6日 * @description */ public class HouseCorp extends Corp { @Override protected void produce() { System.out.println("房地产在盖房子~~"); } @Override protected void shell() { System.out.println("房地产在销售房子~~~"); } @Override public void makeMoney() { super.makeMoney(); System.out.println("房地产公司大赚一笔~~~~~"); } }
-
ClothesCorp
package com.peng.ql; /** * @author kungfu~peng * @data 2017年12月6日 * @description */ public class ClothesCorp extends Corp { @Override protected void produce() { System.out.println("服装公司在生产衣服~~"); } @Override protected void shell() { System.out.println("服装公司销售衣服~~~"); } @Override public void makeMoney() { super.makeMoney(); System.out.println("服装公司大赚一笔~~~~~"); } }
-
Client
package com.peng.ql; /** * @author kungfu~peng * @data 2017年12月6日 * @description */ public class Client { public static void main(String[] args) { System.out.println("富翁第一步:房地产"); HouseCorp hc = new HouseCorp(); hc.makeMoney(); System.out.println("富翁第二步:服饰"); ClothesCorp cc = new ClothesCorp(); cc.makeMoney(); } }
-
执行结果
富翁第一步:房地产 房地产在盖房子~~ 房地产在销售房子~~~ 房地产公司大赚一笔~~~~~ 富翁第二步:服饰 服装公司在生产衣服~~ 服装公司销售衣服~~~ 服装公司大赚一笔~~~~~
-
- 类图
- 富翁已经做成了,哈哈,代码的世界真的是美妙啊
- 但是服装公司不是特别的挣钱啊,那么现在什么挣钱啊?苹果,对,但不是吃的那个苹果,是IPhone手机
-
好了,设计思路已经有了,现在用勤劳的小手来实现一下吧!
- 类图
-
代码
-
Corp
package com.peng.ql; /** * @author kungfu~peng * @data 2017年12月6日 * @description */ public abstract class Corp { // 生产 protected abstract void produce(); // 销售 protected abstract void shell(); // 赚钱--模板方法 public void makeMoney() { this.produce(); this.shell(); } }
-
HouseCorp
package com.peng.ql; /** * @author kungfu~peng * @data 2017年12月6日 * @description */ public class HouseCorp extends Corp { @Override protected void produce() { System.out.println("房地产在盖房子~~"); } @Override protected void shell() { System.out.println("房地产在销售房子~~~"); } @Override public void makeMoney() { super.makeMoney(); System.out.println("房地产公司大赚一笔~~~~~"); } }
-
IpadCorp
package com.peng.ql; /** * @author kungfu~peng * @data 2017年12月6日 * @description */ public class IPadCorp extends Corp { @Override protected void produce() { System.out.println("生产Ipad~~"); } @Override protected void shell() { System.out.println("销售Ipad~~~"); } @Override public void makeMoney() { super.makeMoney(); System.out.println("Ipad公司大赚一笔~~~~~"); } }
-
Client
package com.peng.ql; /** * @author kungfu~peng * @data 2017年12月6日 * @description */ public class Client { public static void main(String[] args) { System.out.println("富翁第一步:房地产"); HouseCorp hc = new HouseCorp(); hc.makeMoney(); System.out.println("富翁第二步:Ipad"); IPadCorp ic = new IPadCorp(); ic.makeMoney(); } }
-
执行结果
富翁第一步:房地产 房地产在盖房子~~ 房地产在销售房子~~~ 房地产公司大赚一笔~~~~~ 富翁第二步:Ipad 生产Ipad~~ 销售Ipad~~~ Ipad公司大赚一笔~~~~~
-
- 类图
-
现在富翁做到了,但是有个问题:就是之前的服装公司去哪了,难道要新建一个公司就要抛弃原来的公司,再重新建立新的公司?有钱也不能这么任性!那该怎么做呢?
-
废物利用,好主意,把公司的建筑留下,把产品改变一下就行了,然后生产新的产品,听起来还不错,不妨一试
- 类图的设计
-
看起来还不错,代码实现一下
-
Corp
package ql2; /** * @author kungfu~peng * @data 2017年12月6日 * @description */ public abstract class Corp { // 产品对象 private Product product; // 通过构造函数将产品传入 public Corp(Product product) { super(); this.product = product; } // 赚钱--模板方法 public void makeMoney() { // 生产产品 this.product.beProducted(); // 销售产品 this.product.beSelled(); } }
-
HouseCorp
package ql2; /** * @author kungfu~peng * @data 2017年12月6日 * @description */ public class HouseCorp extends Corp { public HouseCorp(Product product) { super(product); } @Override public void makeMoney() { super.makeMoney(); System.out.println("房地产公司大赚一笔~~~~~"); } }
-
ShanZhaiCorp
package ql2; /** * @author kungfu~peng * @data 2017年12月6日 * @description */ public class ShanZhaiCorp extends Corp { public ShanZhaiCorp(Product product) { super(product); } @Override public void makeMoney() { super.makeMoney(); System.out.println("山寨公司大赚一笔~~~~~"); } }
-
Product
package ql2; /** * @author kungfu~peng * @data 2017年12月6日 * @description */ public abstract class Product { // 生产产品 public abstract void beProducted(); // 销售产品 public abstract void beSelled(); }
-
House
package ql2; /** * @author kungfu~peng * @data 2017年12月6日 * @description */ public class House extends Product { @Override public void beProducted() { System.out.println("盖房中~~"); } @Override public void beSelled() { System.out.println("销售房屋中~~~"); } }
-
Ipad
package ql2; /** * @author kungfu~peng * @data 2017年12月6日 * @description */ public class Ipad extends Product { @Override public void beProducted() { System.out.println("生产ipad中~~"); } @Override public void beSelled() { System.out.println("销售ipad中~~~"); } }
-
Client
package ql2; /** * @author kungfu~peng * @data 2017年12月6日 * @description */ public class Client { public static void main(String[] args) { // 致富之路之房地产 Corp cp = new HouseCorp(new House()); cp.makeMoney(); // 致富之路中之山寨产品 cp = new ShanZhaiCorp(new Ipad()); cp.makeMoney(); } }
-
执行结果
盖房中~~ 销售房屋中~~~ 房地产公司大赚一笔~~~~~ 生产ipad中~~ 销售ipad中~~~ 山寨公司大赚一笔~~~~~
-
- 类图的设计
-
- 现在的改造基本完成,现在看下改造完后的好处
- 扩展公司:直接继承Corp,然后建立新的公司
- 扩展产品:直接继承Product,然后创建新的产品
- 高层模块只需要修改具体的实现类就可以了
桥梁模式的应用
- Bridge Pattern
- 也叫做桥接模式
- Decouple an abstraction from its implementation so that the two can vary independenty.(将抽象的实现解耦,使得两者可以独立的变化)
- 桥梁模式的重点在“解耦”上
桥梁模式的通用类图
- 类图
- 类图解释
- Abstraction: 抽象化角色
- RefineAbstraction:修正抽象化角色
- Implementor:实现化角色
- ConcreteImplementor具体实现化角色
- 抽象角色引用实现角色---记住这个即可
通用代码
-
Abstraction
package ql3; /** * @author kungfu~peng * @data 2017年12月6日 * @description */ public class Abstraction { // 定义实现化角色 private Implementor imlementor; // 构造函数传入实现化角色 public Abstraction(Implementor imlementor) { super(); this.imlementor = imlementor; } // 自身的属性和方法 public void request() { this.imlementor.doSomething(); } // 获得实现化角色 public Implementor getImlementor() { return imlementor; } }
-
RefineAbstraction
package ql3; /** * @author kungfu~peng * @data 2017年12月6日 * @description */ public class RefinedAbstraction extends Abstraction { // 重写构造函数 public RefinedAbstraction(Implementor imlementor) { super(imlementor); } // 修正父类的行为 @Override public void request() { super.request(); super.getImlementor().doAnything(); } }
-
Implementor
package ql3; /** * @author kungfu~peng * @data 2017年12月6日 * @description */ public abstract class Implementor { // 基本方法 public abstract void doSomething(); public abstract void doAnything(); }
-
ConcreteImplementor1
package ql3; /** * @author kungfu~peng * @data 2017年12月6日 * @description */ public class ConcreteImplementor1 extends Implementor { @Override public void doSomething() { // 业务逻辑处理 } @Override public void doAnything() { // 业务逻辑处理 } }
-
ConcreteImplementor2
package ql3; /** * @author kungfu~peng * @data 2017年12月6日 * @description */ public class ConcreteImplementor2 extends Implementor { @Override public void doSomething() { // 业务逻辑处理 } @Override public void doAnything() { // 业务逻辑处理 } }
桥梁模式的应用
- 桥梁模式的优点
- 抽象和实现分类
- 优秀的扩充能力
- 实现细节对客户透明
桥梁模式的使用场景
- 不希望或不适用继承的场景
- 接口或抽象类不稳定的场景
- 重用性要求高的地方
最佳实践
- 继承的优点有很多,可以把公共的方法或属性抽取,父类封装共性,子类实现特性,这是继承的基本功能,缺点有没有?有父类的方法,子类也必须有这个方法。这是不可选择的,会带来扩展性的问题--重写继承父类的方法,这样风险就太大了
- 桥梁模式:描述类间弱关联关系,这样可以使用桥梁来搭相应的父子类
- 不能说继承不好,它非常好,但是有缺点,可以扬长避短:对于不发生改变的,则可以通过继承来实现;若不能确定是否发生变化,则可以使用桥梁模式来解决,这才是一个完美的世界
声明
- 摘自秦小波《设计模式之禅》第2版;
- 仅供学习,严禁商业用途;
- 代码手写,没有经编译器编译,有个别错误,自行根据上下文改正;