1. 需求
如果我现在有一个N品牌的手机,它有一个小游戏,我要玩游戏,程序应该如何写
2. 代码版本1.0
思路:先写一个此品牌的游戏类,再用客户端调用即可
2.1 游戏类
public class HandsetBrandNGame {
public void run(){
System.out.println("运行N品牌手机游戏");
}
}
2.2 客户端代码
HandsetBrandNGame handsetBrandNGame = new HandsetBrandNGame();
handsetBrandNGame.run();
3. 需求增加
现在又有一个M品牌的手机,也有小游戏,客户端也可以调用,如何做
4. 代码版本2.0
思路:有一个父类手机品牌游戏,然后让N和M品牌的手机游戏都继承于它,这样可以实现同样的运行方法
4.1 手机游戏类
public abstract class HandsetGame {
public abstract void run();
}
4.2 M品牌手机游戏和N品牌手机游戏类
public class HandsetBrandM extends HandsetGame{
@Override
public void run() {
System.out.println("运行M品牌游戏");
}
}
public class HandsetBrandN extends HandsetGame{
@Override
public void run() {
System.out.println("运行N品牌游戏");
}
}
5. 需求再增加
手机增加通讯录功能
6. 代码版本3.0
6.1 UML类图
6.2 手机类
public class HandsetBrand {
public void run(){}
}
6.3 手机品牌M和手机品牌N类
public class HandsetBrandM extends HandsetBrand{
}
public class HandsetBrandN extends HandsetBrand{
}
6.4 下属的各自通讯录类和游戏类
public class HandsetBrandMGame extends HandsetBrandM{
@Override
public void run() {
System.out.println("运行M品牌手机游戏");
}
}
public class HandsetBrandNGame extends HandsetBrandN{
@Override
public void run() {
System.out.println("运行N品牌游戏");
}
}
public class HandsetBrandMAddressList extends HandsetBrandM{
@Override
public void run() {
System.out.println("运行M品牌通讯录");
}
}
public class HandsetBrandNAddressList extends HandsetBrandN{
@Override
public void run() {
System.out.println("运行N品牌手机通讯录");
}
}
6.5 客户端代码
HandsetBrand ab;
ab = new HandsetBrandMAddressList();
ab.run();
ab=new HandsetBrandMGame();
ab.run();
ab = new HandsetBrandNAddressList();
ab.run();
ab=new HandsetBrandNGame();
ab.run();
6.6 弊端
假如再增加一个“播放音乐功能”,那么又需要增加3个类,这时候用继承就会带来麻烦。因为对象的继承关系是在编译时就定义好了,所以无法在运行时改变从父类继承的实现。子类的实现与它的父类有非常紧密的依赖关系,以至于父类实现中的任何变化必然会导致子类发生变化。当你需要复用子类时,如果继承下来的实现不适合解决新的问题,则父类必须重写或被其他更适合的类替换。这种依赖关系限制了灵活性并最终限制了复用性
在面向对象设计中,我们还有一个很重要的设计原则,那就是合成/聚合复用原则。即优先使用对象合成/聚合,而不是类继承。
7. 合成/聚合复用原则
聚合表示一种弱的’拥有’关系,体现的是A对象可以包含B对象,但B对象不是A对象的一部分;合成则是一种强的’拥有’关系,体现了严格的部分和整体的关系,部分和整体的生命周期一样。
7.1 优点
优先使用对象的合成/聚合将有助于你保持每个类被封装,并被集中在单个任务上。这样类和类继承层次会保持较小规模,并且不太可能增长为不可控制的庞然大物。
8. 桥接模式
桥接模式(Bridge),将抽象部分与它的实现部分分离,使它们都可以独立地变化。实现指的是抽象类和它的派生类用来实现自己的对象
8.1 案例代码
8.1.1 UML类图
8.1.2 Implementor类
public abstract class Implementor {
public abstract void operation();
}
8.1.3 ConcreteImplementorAConcreteImplementorB等派生类
public class ConcreteImplementorA extends Implementor{
@Override
public void operation() {
System.out.println("具体实现A的方法执行");
}
}
public class ConcreteImplementorB extends Implementor{
@Override
public void operation() {
System.out.println("具体实现B的方法执行");
}
}
8.1.4 Abstraction类
public abstract class Abstraction {
protected Implementor implementor;
public void setImplementor(Implementor implementor){
this.implementor = implementor;
}
public abstract void operation();
}
8.1.5 RefinedAbstraction类
public class RefinedAbstraction extends Abstraction{
@Override
public void operation() {
System.out.print("具体的Abstraction");
implementor.operation();
}
}
8.1.6 客户端代码
Abstraction ab;
ab= new RefinedAbstraction();
ab.setImplementor(new ConcreteImplementorA());
ab.operation();
ab.setImplementor(new ConcreteImplementorB());
ab.operation();
9. 代码版本4.0(桥接模式实现)
9.1 UML类图
9.2 手机软件抽象类
//手机软件
public abstract class HandsetSoft {
//运行
public abstract void run();
}
9.3 游戏、通讯录等具体类
//手机游戏
public class HandsetGame extends HandsetSoft{
@Override
public void run() {
System.out.println("手机游戏");
}
}
//手机通讯录
public class HandsetAddressList extends HandsetSoft{
@Override
public void run() {
System.out.println("通讯录");
}
}
9.4 手机品牌类
//手机品牌
public abstract class HandsetBrand {
protected HandsetSoft soft;
//设置手机软件
public void setSoft(HandsetSoft soft) {
this.soft = soft;
}
//运行
public abstract void run();
}
9.5 品牌N品牌M具体类
public class HandsetBrandM extends HandsetBrand{
@Override
public void run() {
System.out.print("品牌M");
}
}
public class HandsetBrandN extends HandsetBrand{
@Override
public void run() {
System.out.print("品牌N");
}
}
9.6 客户端代码
HandsetBrand ab;
ab = new HandsetBrandM();
ab.setSoft(new HandsetGame());
ab.run();
ab.setSoft(new HandsetAddressList());
ab.run();
HandsetBrand ab2;
ab2= new HandsetBrandN();
ab2.setSoft(new HandsetGame());
ab2.run();
ab2.setSoft(new HandsetAddressList());
ab2.run();