两个手机品牌,都有游戏,两个手机是不同的操作系统。怎么写?
该有一个父类手机品牌游戏,让N和M品牌手机游戏都继承它。
基于这个模型,那如果新增加一个手机品牌,并且每个手机品牌增加各种功能,例如:游戏、通讯录、MP3等。
那样就会变得非常麻烦。
继承的问题
无法在运行时改变从父类继承的实现,子类和父类依赖关系紧密,父类中任何变化都会导致子类发生变化。
当复用子类时,如果继承下来的子类不适合解决新问题,则父类必须重写或被其他更适合的类替换,导致限制了复用性。
面向对象中首先使用合成/聚合复用原则,即优先使用对象合成/聚合,而不是类继承。
聚合
表示“弱”的拥有关系,A对象可包含B对象,但B对象不是A对象的一部分;
合成
是一种“强”的拥有关系,部分和整体的生命周期是一样的。
大雁和翅膀就类似于合成关系;每只大雁是属于一个雁群,一个雁群有多只大雁,所以大雁和雁群是聚合关系。
好处
优先使用对象的合成/聚合有助于你保持每个类被封装,并被集中在单个任务上。这样类和类继承层次会保持较小规模,且不太可能增长为不控制的庞然大物。
根据这个原则,修改之前的类结构。
手机品牌包含有手机软件,但软件不是品牌的一部分,所以是聚合关系。
手机软件
public abstract class HandsetSoft {
public abstract void run();
}
游戏、通讯录等具体类
public class HandsetGame extends HandsetSoft {
@Override
public void run(){
println("游戏");
}
}
public class HandsetAddress extends HandsetSoft {
@Override
public void run(){
println("通讯录");
}
}
手机品牌类
public abstract class HandsetBrand {
//弱聚合
protected HandsetSoft soft;
//设置手机软件
public void setHandsetSoft(HandsetSoft soft){
this.soft = soft;
}
//运行
public abstract void run();
}
品牌N品牌M等具体类
//品牌N
class HandsetBrandN extends HandsetBrand {
@Override
public void run(){
soft.run();
}
}
//品牌M
class HandsetBrandM extends HandsetBrand {
@Override
public void run(){
soft.run();
}
}
客户端
public class Main {
HandsetBrand ab;
//创建品牌N
ab = new HandsetBrandN();
//给品牌N安装游戏
ab.setHandsetSoft(new HandsetGame());
ab.run();
//给品牌N安装通讯录
ab.setHandsetSoft(new HandsetAddress());
ab.run();
}
将抽象部分和它的实现部分分离,使它们都可以独立的变化。
就像之前例子,让手机既可以按品牌分类,也可以按功能来分类。
Implementor类
public abstract class Implementor {
public abstract void operation();
}
ConcreteImplementorA和ConcreteImplementorB等派生类
public class ConcreteImplementorA extends Implementor{
@Override
public void operation(){
println("具体实现A的方法执行");
}
}
public class ConcreteImplementorB extends Implementor{
@Override
public void operation(){
println("具体实现B的方法执行");
}
}
Abstraction类
public abstract class Abstraction {
protected Implementor impl;
public Abstraction(Implementor impl){
this.impl = impl;
}
public abstract void operation();
}
RefinedAbstraction类
public class RefinedAbstraction extends Abstraction {
public RefinedAbstraction(Implementor impl){
super(impl);
}
@Override
public void operation(){
impl.operation();
}
}
客户端实现
public class Main {
public static void main(String[] args){
Abstraction ab = new RefinedAbstraction(new ConcreteImplementorA());
ab.operation();
ab = new RefinedAbstraction(new ConcreteImplementorB());
ab.operation();
}
}