不知道大家是否还记得我之前在建造者模式的时候卖的电脑,嗯,不记得也没关系,我们再来看一下。
public class Computer {
private String screen;
private String cpu;
private String keyboard;
private String disk;
/**
* 主机
*/
private String engine;
private String cache;
public Computer(String screen, String cpu, String keyboard, String disk, String engine,
String cache) {
this.screen = screen;
this.cpu = cpu;
this.keyboard = keyboard;
this.disk = disk;
this.engine = engine;
this.cache = cache;
}
}
之前我们主卖台式机,各种配件都可以根据用户的需求进行组装。随着笔记本电脑技术的发展,我们发现笔记本电脑越来越受客户的喜爱。那么我们就打算大量生产笔记本。这时候问题来了,台式机是可以现场通过配件组装的,但是呢笔记本都是出厂配置好的,而且各种配件的类型很多,比如说intel5, intel7,AMD等处理器,有了2G,4G,6G,8G的内存条。这样的话,我们如果使用建造者模式的话,只按照CPU和内存条的类型的话,那我就要件12个建造者类来满足不同类型的生产,另外还有华为和苹果两个品牌,那创建的类就过于多了。那么我们怎么来解决呢?
我们先来看实现代码,再来解释其原理。我们主要以CPU和Cache作为扩展维度,其余同理。
我们是卖华为和苹果的笔记本电脑,并且分别有i7,i5,AMD的cpu,有2G,4G,8G的内存,就相当于顾客在购买笔记本时选择不同的配置,价格不一致是一样的。当然笔记本都是提前生产好的,而不是根据顾客需求进行配置的。
public abstract class Laptop {
private String screen;
protected Cpu cpu;
private String keyboard;
private String disk;
/**
* 主机
*/
private String engine;
protected Cache cache;
public Laptop(Cache cache, Cpu cpu) {
this.cpu = cpu;
this.cache = cache;
}
public abstract void play();
}
public class HuaweiLaptop extends Laptop {
public HuaweiLaptop(Cache cache, Cpu cpu) {
super(cache, cpu);
}
@Override
public void play() {
System.out.println("I am playing huawei laptop with cpu: " + cpu.type + " cache: " + cache.size);
}
}
public class AppleLaptop extends Laptop {
public AppleLaptop(Cache cache, Cpu cpu) {
super(cache, cpu);
}
@Override
public void play() {
System.out.println("I am playing apple laptop with cpu: " + cpu.type + " cache: " + cache.size);
}
}
定制CPU和Cache的规范
public abstract class Cache {
public int size;
public void setSize(int size) {
this.size = size;
}
}
public abstract class Cpu {
public String type;
void setType(String type) {
this.type = type;
}
}
实现不同类型的CPU和Cache
public class Intel7Cpu extends Cpu {
public Intel7Cpu() {
setType("Intel7");
}
}
public class Intel5Cpu extends Cpu {
public Intel5Cpu() {
setType("Intel5");
}
}
public class AmdCpu extends Cpu {
public AmdCpu() {
setType("AMD");
}
}
public class TwoCache extends Cache {
public TwoCache() {
setSize(2);
}
}
public class FourCache extends Cache {
public FourCache() {
setSize(4);
}
}
public class EightCache extends Cache {
public EightCache() {
setSize(8);
}
}
执行代码
public static void main(String[] args) {
// i want to buy huawei laptop intel 7 8G cache laptop
Intel7Cpu intel7Cpu = new Intel7Cpu();
EightCache eightCache = new EightCache();
Laptop huaweiLaptop = new HuaweiLaptop(eightCache, intel7Cpu);
huaweiLaptop.play();
// i want to buy apple laptop intel 5 4G cache laptop
Intel5Cpu intel5Cpu = new Intel5Cpu();
FourCache fourCache = new FourCache();
Laptop appleLaptop = new AppleLaptop(fourCache, intel5Cpu);
appleLaptop.play();
}
执行结果
I am playing huawei laptop with cpu: Intel7 cache: 8
I am playing apple laptop with cpu: Intel5 cache: 4
整体代码走下来,我感觉是有点迷惑的,桥接模式在其中起到了什么作用呢?我们先来分析它做了什么,它在Laptop中设定了CPU和Cache的抽象类,不指定具体的实现类,然后在创建Laptop的过程中,将具体的CPU和Cache的实现类添加到Laptop中。其作用呢?由于CPU和Cache的类型较多,如果使用特定具体类的话,比如Intel5EightHuaweiLaptop,Intel5FourHuaweiLaptop,Intel7EightHuaweiLaptop等等,就会产生大量的具体类,十分臃肿。那为什么学习完了之后,会迷惑呢?我觉得是是在平常工作中,我们经常会读到类似桥接模式的代码,用父类去代替子类,来保证通用性,所以我们会在下意识中觉得这就是一种很普通的实现方式,而不会觉得这是一种设计模式,所以会迷惑。而实际上呢,设计模式就是在大量通用解决方法中提炼出来的解决问题的模式,所以桥接模式是一种非常常见的设计模式,常见到我们并不认为这是一种设计模式!
将上面的话抽象一下,桥接模式:将一个大类或一系列紧密相关的类拆分为抽象和实现两个独立的层次结构, 从而能在开发时分别使用。尤其常见于一个大类有多个独立维度的小类组合,并且这些类有多种类型的场景。其优点在大类组合下的各个小类都是独立维度,各自相互无关联,大类不会因为小类的变化而变化,也不会因为小类类型的增加而导致大类数量的急剧增加!