资料来源<大话程序设计模式>
1、手机品牌和手机软件的兼容性问题。假如N牌的手机,玩游戏,单类就可以实现,然后客户端调用。
<span style="font-size:18px;">Class Game
{
public void Game()
{
System.out.println("运行N品牌的手机游戏");
}
}
客户端调用:
Game game=new Game();
game.run();</span>
2、现在又来了M牌的手机游戏,那我就会想到抽象手机游戏,让M、N继承抽象类,实现run方法。UML图如下所示。
3、如果又要添加非游戏类的通讯录功能的话,上面的抽象与继承就不行了。可能会想到抽象手机品牌,让具体品牌继承抽象品牌,然后让游戏或通讯功能继承具体品牌,UML图如下。
4、如果又要增加一个品牌的手机的话,就要增加品牌类和它的子类。如果又要增加MP3、视频功能的话,所有的子类都得改变。
如果是这样的方式可不可以呢?UML如下所示。
同样如果要增加手机功能,要做的改动也是非常大的。
在上述实例中,一直用抽象和继承来解决品牌和功能增加的问题。可是继承有时候不能解决好问题,相反,会带来很多的麻烦。
对象的继承关系在编译时就定义好了,所以无法在运行时改变从父类继承的实现。子类的实现与它的父类有非常紧密的依赖关系,以至于父类实现中的任何变化必然会导致子类发生变化。当你需要复用子类时,如果继承下来的实现不合适解决新的问题,则父类必须重写或被其他更合适的类替换。这种依赖关系限制了灵活性并最终限制了复用性。<大话设计模式>
继承是一种强耦合的结构,父类变,子类必须变,所以我们在使用继承的时候,一定是在‘is-a’的关系下再考虑使用。针对这种问题的出现,提出新的解决办法。
1、合成/聚合复用原则
尽量使用合成/聚合复用原则,尽量不要使用类继承。
聚合表示一种弱的‘拥有’关系,体现的是A对象可以包含B对象,但是B对象不是A对象的一部分;合成则是一种强的‘拥有’关系,体现了严格的部分和整体的关系,部分和整体的生命周期是一样的。
大雁的翅膀与大雁是整体和部分的关系。
大雁和雁群是聚合关系。
上述问题解决如下:
手机品牌中包含手机软件,是聚合关系,UML图实现如下:
代码实现如下:
1、SoftWare软件抽象类
<span style="font-size:18px;">public abstract class SoftWare
{
public abstract void run();
}
</span>
2、通讯录AddressList,游戏Game实现类
<span style="font-size:18px;">public class Game extends SoftWare
{
@Override
public void run()
{
// TODO Auto-generated method stub
System.out.println("运行手机游戏");
}
}
class AddressList extends SoftWare
{
@Override
public void run()
{
// TODO Auto-generated method stub
System.out.println("运行手机通讯录");
}
}
</span>
3、手机品牌类Brand
<span style="font-size:18px;">public abstract class Brand
{
protected SoftWare software;
public void setSoftWare(SoftWare software)
{
this.software=software;
}
public abstract void run();
}</span>
4、品牌M和N具体类
<span style="font-size:18px;">public class BrandM extends Brand
{
@Override
public void run()
{
// TODO Auto-generated method stub
super.software.run();
}
}
class BrandN extends Brand
{
@Override
public void run()
{
// TODO Auto-generated method stub
super.software.run();
}
}</span>
上面实现的方式就是桥接模式
桥接模式,将抽象部分与它的实现部分分离,使他们都可以独立的变化。实现指的是抽象类和他的派生类用来实现自己的对象。(也就是手机品牌和软件分离),UML如下所示
桥接模式的代码:
1、Implementor类
<span style="font-size:18px;">public abstract class Implementor
{
public abstract void operation();
}</span>
2、ConcreteImplementA类
<span style="font-size:18px;">public class ConcreteImplementorA extends Implementor
{
@Override
public void operation()
{
// TODO Auto-generated method stub
System.out.println("具体实现A的方法执行");
}
}</span>
3、ConcreteImplementB类<span style="font-size:18px;">public class ConcreteImplementorB extends Implementor
{
@Override
public void operation()
{
// TODO Auto-generated method stub
System.out.println("具体实现B的方法执行");
}
}
</span>
4、Abstraction类
<span style="font-size:18px;">public abstract class Abstraction
{
protected Implementor implementor;
public void setImplementor(Implementor implementor)
{
this.implementor=implementor;
}
public abstract void operation();
}</span>
5、RefinedAbstraction类
<span style="font-size:18px;">public class RefinedAbstraction extends Abstraction
{
@Override
public void operation()
{
// TODO Auto-generated method stub
implementor.operation();
}
}</span>
6、客户端实现
<span style="font-size:18px;">public class client
{
public static void main(String[] args)
{
Abstraction ab=new RefinedAbstraction();
ab.setImplementor(new ConcreteImplementorA());
ab.operation();
ab.setImplementor(new ConcreteImplementorB());
ab.operation();
}}public class client
{
public static void main(String[] args)
{
Abstraction ab=new RefinedAbstraction();
ab.setImplementor(new ConcreteImplementorA());
ab.operation();
ab.setImplementor(new ConcreteImplementorB());
ab.operation();
}
}
</span>