对 桥接模式 的个人理解,以及与 工厂方法模式、建造者模式 的结合运用
2017-06-23 04:52
495 查看
学习了一段时间设计模式,就想分享一下自己的理解, 欢迎大家多多指点,指出不足之处哈
桥接模式:以商店与手机为例子来描述,先从简单的依赖关系说起
上面这类图很简单,就是Phone接口有两个实现。Store只依赖Phone接口,不依赖具体实现,这样方便Store更换手机。
如果现在,想增加个实现,NokiaPhone,而且有以下要求:
1、NokiaPhone的charge方法,要跟SonyPhone的一样,同样是快充。
2、NokiaPhone的unlock方法,要跟ApplePhone的一样,同样是指纹解锁。
看到第1点,就让人毫不犹豫想到,可以让NokiaPhone继承SonyPhone。
接着看到2点,就发现 NokiaPhone继承SonyPhone 带来的问题了。NokiaPhone无法通过继承ApplePhone来重用指纹解锁(不能继承多个类),只能硬生生的复制ApplePhone的过来用。如下
由此可见,继承也会出现代码不能复用的问题
除此之外,若现在NokiaPhone想增加个功能 照相(takePicture)。
由于Store依赖的是Phone,所以Phone得加takePicture方法
小结:继承,不能很好解决代码重用,而且不方便扩展。
再看回原来的SonyPhone、ApplePhone实现的方法,可以归类得出
charge: 普通充电,快充
unlock: 指纹解锁,面部解锁
之后新增的NokiaPhone相当于从上面每个功能,分别抽取所需的实现来组合而成。
这样有没感觉,若将 普通充电,快充,指纹解锁,面部解锁 分别放到不同的类,然后只要将按需set到NokiaPhone中即可。
事实上桥接模式,就类似这思路。
大家应该发现,这类图跟大家经常看到的不同,Abstraction缺少了个子类RefineAbstraction。由于本小白一直想不通RefineAbstraction的作用,所以也想通过这文章,希望各位大神能拔刀相助。
下面根据本例画上相应的类图
用了桥接模式的话,Store就可以随意组合出所需的手机种类。
大家可能问,用户类Store要是更换其它种类手机,就得修改代码,不科学呀。
这问题就牵涉到 如何获取实例对象 问题,桥接模式解决的只是如何处理实例对象依赖 问题。(后面将提到如何结合 工厂方法模式,建造者模式 来方便获取不同的手机)
此时若新增 照相功能(takePicture)
小结:一类产品(本例的Phone)若多维上有多个不同实现(charge、camera、takePicture等方法都有多个实现)。此时若使用继承,会出现 代码难以重用、新增维度不方便 等问题,此时适合使用桥接模式
工厂方法模式-建造者模式-桥接模式:终于到高潮了,请先阅读 对 工厂模式与建造者模式 的个人理解,以及结合运用
总结:
桥接模式将一类产品(本例的手机)的多维变化(charge、unlock方法各有不同实现),抽取成单独的类(Charger、Locker等实现)。
建造者模式的Builder角色负责从每个维度选取所需的实现类
工厂类,最后就变成只需将对应的Builder传入到Director里,调用Director开始按顺序建造。
桥接模式:以商店与手机为例子来描述,先从简单的依赖关系说起
public interface Phone { /** 充电 **/ void charge(); /** 解锁 **/ void unlock(); } public class ApplePhone implements Phone { public void charge() { System.out.println("普通充电"); } public void unlock() { System.out.println("指纹解锁"); } } public class SonyPhone implements Phone { public void charge() { System.out.println("快充"); } public void unlock() { System.out.println("面部解锁"); } } public class Store { /** * 补充手机 */ public void supplyPhone() { Phone phone = new SonyPhone(); // 补充手机逻辑... System.out.println("补充手机完成"); } }
上面这类图很简单,就是Phone接口有两个实现。Store只依赖Phone接口,不依赖具体实现,这样方便Store更换手机。
如果现在,想增加个实现,NokiaPhone,而且有以下要求:
1、NokiaPhone的charge方法,要跟SonyPhone的一样,同样是快充。
2、NokiaPhone的unlock方法,要跟ApplePhone的一样,同样是指纹解锁。
看到第1点,就让人毫不犹豫想到,可以让NokiaPhone继承SonyPhone。
接着看到2点,就发现 NokiaPhone继承SonyPhone 带来的问题了。NokiaPhone无法通过继承ApplePhone来重用指纹解锁(不能继承多个类),只能硬生生的复制ApplePhone的过来用。如下
public class NokiaPhone extends SonyPhone { public void unlock() { System.out.println("指纹解锁"); } }
由此可见,继承也会出现代码不能复用的问题
除此之外,若现在NokiaPhone想增加个功能 照相(takePicture)。
由于Store依赖的是Phone,所以Phone得加takePicture方法
public interface Phone { /** 充电 **/ void charge(); /** 解锁 **/ void unlock(); /** 照相 **/ void takePicture(); } public class ApplePhone implements Phone { public void charge() { System.out.println("普通充电"); } public void unlock() { System.out.println("指纹解锁"); } public void takePicture() { // 空实现 return; } } public class SonyPhone implements Phone { public void charge() { System.out.println("快充"); } public void unlock() { System.out.println("面部解锁"); } public void takePicture() { // 空实现 return; } } public class NokiaPhone extends SonyPhone { public void unlock() { System.out.println("指纹解锁"); } public void takePicture() { System.out.println("双摄"); } }从代码看,一旦其中一个实现增加特有的功能,其它的实现都得修改,增加很多空实现的代码。
小结:继承,不能很好解决代码重用,而且不方便扩展。
再看回原来的SonyPhone、ApplePhone实现的方法,可以归类得出
charge: 普通充电,快充
unlock: 指纹解锁,面部解锁
之后新增的NokiaPhone相当于从上面每个功能,分别抽取所需的实现来组合而成。
这样有没感觉,若将 普通充电,快充,指纹解锁,面部解锁 分别放到不同的类,然后只要将按需set到NokiaPhone中即可。
事实上桥接模式,就类似这思路。
大家应该发现,这类图跟大家经常看到的不同,Abstraction缺少了个子类RefineAbstraction。由于本小白一直想不通RefineAbstraction的作用,所以也想通过这文章,希望各位大神能拔刀相助。
下面根据本例画上相应的类图
public interface Locker { void unlock(); } public class FaceLocker implements Locker { public void unlock() { System.out.println("指纹解锁"); } } public class FingerprintLocker implements Locker { public void unlock() { System.out.println("面部解锁"); } } //////////////////////////// public interface Charger { void charge(); } public class QuickCharger implements Charger { public void charge() { System.out.println("普通充电"); } } public class SimpleCharger implements Charger { public void charge() { System.out.println("快充"); } } //////////////////////////// public class Phone { private Charger charger; private Locker locker; public void charge() { if (charger == null) { return; } charger.charge(); } public void unlock() { if (locker == null) { return; } locker.unlock(); } public void setCharger(Charger charger) { this.charger = charger; } public void setLocker(Locker locker) { this.locker = locker; } } //////////////////////////// public class Store { /** * 补充手机 */ public void supplyPhone() { Phone phone = getNokiaPhone(); // 补充手机逻辑... System.out.println("补充手机完成"); } private Phone getSonyPhone(){ Phone phone = new Phone(); phone.setCharger(new QuickCharger()); phone.setLocker(new FaceLocker()); return phone; } private Phone getApplePhone(){ Phone phone = new Phone(); phone.setCharger(new SimpleCharger()); phone.setLocker(new FingerprintLocker()); return phone; } private Phone getNokiaPhone(){ Phone phone = new Phone(); phone.setCharger(new QuickCharger()); phone.setLocker(new FingerprintLocker()); return phone; } }
用了桥接模式的话,Store就可以随意组合出所需的手机种类。
大家可能问,用户类Store要是更换其它种类手机,就得修改代码,不科学呀。
这问题就牵涉到 如何获取实例对象 问题,桥接模式解决的只是如何处理实例对象依赖 问题。(后面将提到如何结合 工厂方法模式,建造者模式 来方便获取不同的手机)
此时若新增 照相功能(takePicture)
public interface Camera { void takePicture(); } public class DoubleCamera implements Camera { public void takePicture() { System.out.println("双摄"); } } /////////////////////////////// public class Phone { private Charger charger; private Locker locker; private Camera camera; public void charge() { if (this.charger == null) { return; } this.charger.charge(); } public void unlock() { if (locker == null) { return; } this.locker.unlock(); } public void takePicture() { if (this.camera == null) { return; } this.camera.takePicture(); } public void setCharger(Charger charger) { this.charger = charger; } public void setLocker(Locker locker) { this.locker = locker; } public void setCamera(Camera camera) { this.camera = camera; } } /////////////////////////////// public class Store { /** * 补充手机 */ public void supplyPhone() { Phone phone = getNokiaPhone(); // 补充手机逻辑... System.out.println("补充手机完成"); } private Phone getSonyPhone(){ Phone phone = new Phone(); phone.setCharger(new QuickCharger()); phone.setLocker(new FaceLocker()); return phone; } private Phone getApplePhone(){ Phone phone = new Phone(); phone.setCharger(new SimpleCharger()); phone.setLocker(new FingerprintLocker()); return phone; } private Phone getNokiaPhone(){ Phone phone = new Phone(); phone.setCharger(new QuickCharger()); phone.setLocker(new FingerprintLocker()); phone.setCamera(new DoubleCamera()); return phone; } }此时Phone类只需增加一个takePicture方法,而且Store类,只修改了getNokiaPhone的方法(因为只有Nokia需要加照相功能),没有影响到其它方法。
小结:一类产品(本例的Phone)若多维上有多个不同实现(charge、camera、takePicture等方法都有多个实现)。此时若使用继承,会出现 代码难以重用、新增维度不方便 等问题,此时适合使用桥接模式
工厂方法模式-建造者模式-桥接模式:终于到高潮了,请先阅读 对 工厂模式与建造者模式 的个人理解,以及结合运用
public interface PhoneBuilder { void buildCharger(); void buildLocker(); Phone getResult(); } public class ApplePhoneBuilder implements PhoneBuilder { private Phone phone = new Phone(); public void buildCharger() { phone.setCharger(new SimpleCharger()); } public void buildLocker() { phone.setLocker(new FingerprintLocker()); } public Phone getResult() { return phone; } } public class SonyPhoneBuilder implements PhoneBuilder { private Phone phone = new Phone(); public void buildCharger() { phone.setCharger(new QuickCharger()); } public void buildLocker() { phone.setLocker(new FaceLocker()); } public Phone getResult() { return phone; } } /////////////////////////////// public class PhoneDirector { public Phone construct(PhoneBuilder builder) { builder.buildCharger(); builder.buildLocker(); return builder.getResult(); } } public interface PhoneFactory { Phone getPhone(); } public class ApplePhoneFactory implements PhoneFactory { private PhoneDirector director = new PhoneDirector(); public Phone getPhone() { ApplePhoneBuilder builder = new ApplePhoneBuilder(); return director.construct(builder); } } public class SonyPhoneFactory implements PhoneFactory { private PhoneDirector director = new PhoneDirector(); public Phone getPhone() { SonyPhoneBuilder builder = new SonyPhoneBuilder(); return director.construct(builder); } } /////////////////////////////// public class Store { private PhoneFactory phoneFactory; public Store(PhoneFactory phoneFactory) { super(); this.phoneFactory = phoneFactory; } /** * 补充手机 */ public void supplyPhone() { Phone phone = phoneFactory.getPhone(); // 补充手机逻辑... System.out.println("补充" + phone.getBrand() + "手机完成"); } public static void main(String[] args) { StoreB storeB = new StoreB(new SonyPhoneFactory()); storeB.supplyPhone(); } }
总结:
桥接模式将一类产品(本例的手机)的多维变化(charge、unlock方法各有不同实现),抽取成单独的类(Charger、Locker等实现)。
建造者模式的Builder角色负责从每个维度选取所需的实现类
工厂类,最后就变成只需将对应的Builder传入到Director里,调用Director开始按顺序建造。
相关文章推荐
- 对 工厂模式与建造者模式 的个人理解,以及结合运用
- 个人对设计模式的理解-->桥接模式
- vue router结合文档以及个人理解
- java设计模式(工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式、适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式,。 行为型模式,共十一种:策略模式、模板方法)
- 关于建造者模式的个人理解
- andorid 中 MVP模式 个人理解与运用(原创)
- 关于桥接模式的个人理解
- 建造者模式的个人理解
- 个人对理想团队模式构建的设想以及对软件流程的理解
- 我谈Silverlight架构和模式运用1-- ModelView模式最简单教程-讲解无代码触发事件,以及类型转换器的强大功能
- 关于工厂模式和建造者模式的理解
- 极速理解设计模式系列:9.工厂方法模式(Factory Method Pattern)
- 个人对继承理解以及虚析构函数的理解
- 深入理解JavaScript系列(27):设计模式之建造者模式
- SSAS 工作笔记(3) 结合网上资料和个人实践理解整理
- 深入理解JavaScript系列(44):设计模式之桥接模式
- 极速理解设计模式系列:7.桥接模式(Bridge Pattern)
- 极速理解设计模式系列:7.桥接模式(Bridge Pattern)
- 深入理解JavaScript系列(27):设计模式之建造者模式
- 设计模式之个人理解--单例模式