今天我要说说我自己,梦想中的我自己,身家过亿,有两个大公司,一个房地产一个服装制造业,两个公司都很赚钱,天天帮我累加财富。我先用类图表示一下我这两个公司:
类图很简单,声明了一个Corp抽象类,定义一个公司的抽象模型,公司首先是要赚钱的,不赚钱谁开公司,先看Corp类的代码:
package com.example.xpeng.myapplication;
/**
* Created by xpeng on 2018/6/2.
* 定义一个公司的抽象类
*/
public abstract class Corp {
/**
* 是公司就应该有生产吧,甭管是什么软件公司还是制造公司
*/
protected abstract void prodece();
/**
* 有产品了,那肯定要销售啊,不销售你公司怎么生存
*/
protected abstract void sell();
//公司是干什么的?赚钱
public void makeMoney(){
//每个公司都是一样,先生产
this.prodece();
//然后销售
this.sell();
}
}
合适的方法存在合适的类中,这个基本上是每本java基础书都会讲的,但是到实际的项目中应用中就不是这么回事儿了,正常的很。我们继续看两个实现类如何实现的,先看HouseCorp类,这个是我最赚钱的公司:
package com.example.xpeng.myapplication;
import android.util.Log;
/**
* Created by xpeng on 2018/6/2.
* 房地产公司
*/
public class HouseCorp extends Corp {
//房地产公司就是盖房子哦
@Override
protected void prodece() {
Log.e("xyz","房地产公司盖房子...");
}
@Override
protected void sell() {
Log.e("xyz","卖房子...");
}
//计算利润
public void makeMoney(){
super.makeMoney();
Log.e("xyz","房地产赚大钱了");
}
}
然后再来看服装公司,虽然不景气,但好歹也是赚钱的:
package com.example.xpeng.myapplication;
import android.util.Log;
/**
* Created by xpeng on 2018/6/2.
*/
public class ClothesCorp extends Corp {
//服装公司生产的就是衣服了
@Override
protected void prodece() {
Log.e("xyz","服装公司生产衣服...");
}
@Override
protected void sell() {
Log.e("xyz","卖衣服...");
}
//计算利润
public void makeMoney(){
super.makeMoney();
Log.e("xyz","服装公司赚小钱了");
}
}
两个公司都有了,那肯定有人关心两个公司的运营情况啊,看实现:
//先找到我的公司
HouseCorp houseCorp = new HouseCorp(house);
//看我怎么挣钱
houseCorp.makeMoney();
上述代码完全可以描述我现在的公司,但是你要知道万物都是运动的,你要用运动的眼光看问题,我公司也会有发展,终于有一天我觉得赚钱速度太慢,于是我上下疏通,左右打关系,终于开辟了一条赚钱的康庄大道:生产山寨产品,什么产品呢?市场上什么牌子的东西火爆我就生产什么牌子的东西。
企业方向定下来了,通过调查,市场上前段时间比较火爆的是苹果ipad,那咱就生产这个,把服装厂改成iPod生产厂,看类图变化:
好,我的企业改头换面了,开始生产iPod产品了,看我IPodCorp类的实现:
package com.example.xpeng.myapplication;
import android.util.Log;
/**
* Created by xpeng on 2018/6/2.
* 我是山寨老大,你流行啥我就生产啥
* 现在流行iPod
*/
public class IPodCorp extends Corp {
@Override
protected void prodece() {
Log.e("xyz","我生产iPod...");
}
@Override
protected void sell() {
Log.e("xyz"," ipod畅销... ");
}
@Override
public void makeMoney() {
super.makeMoney();
Log.e("xyz","我赚钱啊");
}
}
这个场子修改完毕了,我这个董事长还要去看看到底生产什么了,看看最终调用:
//先找到我的公司
HouseCorp houseCorp = new HouseCorp(house);
//看我怎么挣钱
houseCorp.makeMoney();
IPodCorp iPodCorp = new IPodCorp();
iPodCorp.makeMoney();
确实,只修改了几句话,我的服装厂就开始变成山寨iPod生产车间,然后开始赚钱了。但是有问题啊,我这个是山寨工厂,要及时生产出市场上流行产品,转型要快,要灵活,今天从生产iPod转为生产MP4,明天再转为生产上网本,那么问题来了,每次我的厂房,我的工人,我的设备都在,不可能每次我换个山寨产品我的厂子就彻底不要了,这不行,成本忒高亮点,那怎么办?
Corp类和product类建立一个关联关系,可以彻底解决我以后山寨公司生产产品的问题,看程序说话,先看Product抽象类:
package com.example.xpeng.myapplication;
/**
* Created by xpeng on 2018/6/2.
* 这是我集团公司的产品类
*/
public abstract class Product {
//甭管是什么产品它总是要被生产出来的
public abstract void beProducted();
//生产出来的东西,一定要销售出去,否则赔本啊
public abstract void beSelled();
}
简单,忒简单,看House产品类:
package com.example.xpeng.myapplication;
import android.util.Log;
/**
* Created by xpeng on 2018/6/2.
* 这是我集团公司盖的房子
*/
public class House extends Product {
//豆腐渣就豆腐渣呗,好歹也是个房子
@Override
public void beProducted() {
Log.e("xyz", "生产出的房子是这个样子的...");
}
//虽然是豆腐渣,也是能够销售出去的
@Override
public void beSelled() {
Log.e("xyz", " 生产出的房子卖出去... ");
}
}
不多说,看Clothes产品类:
package com.example.xpeng.myapplication;
import android.util.Log;
/**
* Created by xpeng on 2018/6/2.
* 我们集团生产的衣服
*/
public class Clothes extends Product {
@Override
public void beProducted() {
Log.e("xyz","生产出的衣服是这个样子的...");
}
@Override
public void beSelled() {
Log.e("xyz","生产出的衣服卖出去了... ");
}
}
下面是iPad产品类:
package com.example.xpeng.myapplication;
import android.util.Log;
/**
* Created by xpeng on 2018/6/2.
* 这是生产IPAD
*/
public class IPad extends Product {
@Override
public void beProducted() {
Log.e("xyz", "生产出的iPod是这个样子的...");
}
@Override
public void beSelled() {
Log.e("xyz", " 生产出的iPod卖出去... ");
}
}
产品类是有了,那我们再看Corp抽象类:
package com.example.xpeng.myapplication;
/**
* Created by xpeng on 2018/6/2.
* 定义一个公司的抽象类
*/
public abstract class Corp {
//定义一个产品对象,抽象的了,不知道具体是什么产品
private Product prodect;
//构造函数,由子类定义传递具体的产品进来
public Corp(Product prodect){
this.prodect = prodect;
}
//公司是干什么的?赚钱
public void makeMoney(){
this.prodect.beProducted();
this.prodect.beSelled();
}
}
这里多了个有参构造,其目的是要继承的子类都必须重写自己的有参构造函数,把产品类传递进来,再看子类HouseCorp的实现:
package com.example.xpeng.myapplication;
import android.util.Log;
/**
* Created by xpeng on 2018/6/2.
*/
public class HouseCorp extends Corp {
//定义传递一个House产品进来
public HouseCorp(House house) {
super(house);
}
//房地产公司赚钱
public void makeMoney(){
super.makeMoney();
Log.e("xyz","房地产公司赚大钱了...");
}
}
理解上没有多少难度,不多说,继续看山寨公司的实现:
package com.example.xpeng.myapplication;
import android.util.Log;
/**
* Created by xpeng on 2018/6/2.
* 我是山寨老大,你流行啥我就生产啥
*/
public class ShanZhaiCorp extends Corp {
//产什么产品,不知道,等被调用才知道
public ShanZhaiCorp(Product prodect) {
super(prodect);
}
//狂赚钱
@Override
public void makeMoney() {
super.makeMoney();
Log.e("xyz"," 我赚钱啊啊。。。 ");
}
}
HouseSorp类和ShanZhaiCorp类的区别是在有参构造的参数类型上,HouseCorp类比较明确,我就是只要House类,所以直接定义传递进来的必须是House类,一个类尽可能少的承担责任,那方法也是一样,既然HouseCorp类已经非常明确只生产House产品,那为什么不定义House类型呢?ShanZhaiCorp就不同了,它是确定不了生产什么类型。
好了,两大对应的阵营都已经产生了,那我们再看Client程序:
House house = new House();
//先找到我的公司
HouseCorp houseCorp = new HouseCorp(house);
//看我怎么挣钱
houseCorp.makeMoney();
Clothes clothes = new Clothes();
ClothesCorp clothesCorp = new ClothesCorp(clothes);
clothesCorp.makeMoney();
IPodCorp iPodCorp = new IPodCorp(new IPad());
iPodCorp.makeMoney();
//山寨公司生产的产品很多,不过我只要指定产品就成了
ShanZhaiCorp shanZhaiCorp = new ShanZhaiCorp(new IPad());
Log.e("xyz","山寨公司就是这么运作的...");
shanZhaiCorp.makeMoney();
增加公司,你要么继承Corp类,要么继承HouseCorp或ShanZhaiCorp,不用修改原有的类了:
增加产品,继承Product类,或者继承House类,你要把房子分为公寓房、别墅、商业用房等等;
你都是在扩展,唯一你要修改的就是实现类,你类都增加了哪能不修改调用呢,也就是说Corp类和Product类都可以自由的扩展,而不会对整个应用产生太大的变更,这就是桥梁模式。
看看桥梁模式的通用类图:
看到中间那根带箭头的线了吗?是不是类似一个桥,连接两个类?所以叫桥梁模式。我们再把桥梁模式的几个概念熟悉一下桥梁模式有业务抽象角色和业务实现角色,他们的关系就记住一句话:业务抽象角色引用业务实现角色,或者说业务抽象角色的部分实现是由业务实现角色完成的,很简单,没那么复杂。
桥梁模式的有点就是类间解耦,我们上面已经提到,两个角色都可以扩展下去,不会相互影响,这个也符合OCP原则。
今天说到桥梁模式,那就多扯几句,大家对类的继承有什么看法吗?继承的有点有很多,可以把公共的方法或属性抽取,父类封装共性,子类实现特性,这是继承的基本功能,缺点有没有?有强关联关系,父类有的方法,你子类必须也有这个方法,是不可选择的,那这会带来扩展性问题。
今天讲的这个桥梁模式就是这一问题的解决办法,桥梁模式描述了类间弱关联关系,还说上面的例子,Fatner类完全可以把可能变化的方法放出去,Son子类要有这个烦烦噶很简单,桥梁搭过去,获取这个方法,GrandSon也一样,即使你Son子类不想使用这个方法了,也没关系,对GrandSon不产生影响,他不是从你Son中继承来的方法!
继承不能说它不好,非常好,但是有缺点的,我们可以扬长避短,对于比较明确不发生变化的,则通过继承完成,若不能确定是否会发生变化的,那就认为是会发生变化,则通过桥梁模式来解决,这才是一个完美的世界。
demo下载地址