Java 设计模式 接口 组合 委托

简介

写了几年垃圾代码在设计模式上吃过亏,这次看到一篇文章,觉得讲的太好了,就和讲故事一样,逻辑思路很清晰,来来来 ,玩起来,躁动起来…
看着讲了组合和委托,之前对这个概念不太清晰,现在好好梳理一下,主要研究组合和委托解决的是什么问题

为什么少用继承?

假设: Anmial->鸟类->老鹰,大鹏,凤凰
常规认知的情况:鸟类都会飞,
所以class Bird extend Animal{ protected void fly() }
但有一个例外,鸵鸟也是鸟类,但它不会飞!
class Ostrich extends Bird

继承是实现多态的基础:

  • Bird ostrichBird=new Ostrich()
    鸵鸟即是鸟,又是鸵鸟。那么外部调用方就有可能调用 ostrichBird.fly()父类的方法,但是ostrichBird这个对象是不能飞的,这里逻辑就错误了

那怎么办?怎么解决逻辑错误?

方法一:重写方法,抛出异常

在Ostrich中重写fly()方法中抛出throw UnSupportedMethodException(“I can’t fly”); ostrichBird.fly();

public class Ostrich extends Bird{
 @Override
public void fly(){
throw UnSupportedMethodException("I can't fly"); 
}
}

缺陷:
这样虽然能解决问题,但是增加了没有必要的代码,违背了最小知识的设计原则

什么是动态调用(多态)?
子类重写父类方法,多个子类继承了父类,父类引用了子类,父类调用被重写的方法时,就是分别动态调用的各个子类的方法

方法二:增加一层继承关系来区分

做区分:

再抽离一层public class FlyBird,public class UnFlyBird.
继承UnFlyBird,UnFlyBird没有fly()方法

这样虽然能解决问题

但假如有一种鸟类:天鹅,会游泳会飞,鸵鸟不能游泳不能飞
那么就会产生4种抽象类:
1.会游泳会飞,
2.不会游泳会飞,
3.会游泳不会飞,
4.不会游泳不会飞

那么这样继承的层次就太深了:

Animal->FlyBird,UnFlyBird->FlySwimmingBird,UnFlySwimmingBird,FlyUnSwimmingBird,UnFlyUnSwimmingBird

缺陷1

层次太深,不方法维护和查看代码实现,树形结构,从Root到Item,越往下,层次越深

缺陷2:

父类和子类,强耦合,父类更改代码后,所有子类都会收到影响,比如子类方法中 super.fly()父类方法,父类方法改变

方法三:利用has-a Interface来解决这个问题

利用interface的思想:
把原来以继承方式组装的高层次的树形结构代码层次,转化为以接口这种可装载,可卸载的平层(只有一层) ,因为实现类只有两种情况(有该接口:无该接口)
虽然接口解决了:最小知识原则问题,以及强耦合从is-a转变为了has-a的关系
缺陷:
但接口只声明方法,不定义具体实现,所有会下蛋的鸟类都要实现eggLay()方法,而且eggLay()的逻辑都是一样,都是System.out.println(“会下蛋”);。这时就需要把这部分抽离出来,用一个公共的类来实现

//天鹅
class Swan implements Flyable, Swimmingable, EggLayable {
   
    @Override
    public void fly() {System.out.println("会飞");}

    @Override
    public void swimming() {System.out.println("会游泳");}

    @Override
    public void eggLay() {System.out.println("会下蛋");}
}

class Ostrich implements EggLayable { // 鸵鸟
    @Override
    public void eggLay() {System.out.println("会下蛋");}
}

interface Flyable { void fly();}

interface Swimmingable { void swimming();}

interface EggLayable { void eggLay();}


方法四:接口 组合 委托

组合思想:再加一层类(来把多个类相同功能的方法实现出来),然后在子类声明这个类。
委托思想:其实很容易理解,就是把大家都会干的事情"下蛋"这件事情,委托给公共类eggAbility来处理
组合和委托配合起来使用

public class ExtendInterface {
    /**
     * 让天鹅和鸵鸟下蛋 哈哈哈哈...
      */
    public static void main(String[] args) {
        EggLayable swanEggLay = new Swan();
        swanEggLay.eggLay();
        EggLayable ostrichEggLay = new Ostrich();
        ostrichEggLay.eggLay();
    }
}

// 天鹅
class Swan implements Flyable, Swimmingable, EggLayable {
    Flyable flyAbility = new FlyAbility(); // 组合
    Swimmingable swimmingAbility = new SwimmingAbility();// 组合
    EggLayable eggAbility = new EggAbility();// 组合
    
    public Swan(){System.out.println("我是天鹅");}
    
    @Override //委托
    public void fly() { flyAbility.fly();}
    
    @Override //委托
    public void swimming() {  swimmingAbility.swimming();}

    @Override //委托
    public void eggLay() { eggAbility.eggLay();}
}

class Ostrich implements EggLayable { //鸵鸟
    EggLayable eggAbility = new EggAbility();// 组合
    public Ostrich(){ System.out.println("我是鸵鸟"); }
    @Override
    public void eggLay() {eggAbility.eggLay(); } //委托
}

// interface
interface Flyable { void fly();}

interface Swimmingable { void swimming();}

interface EggLayable { void eggLay();}

// 公共方法的实现类
class FlyAbility implements Flyable {
    @Override
    public void fly() {System.out.println("飞一会儿"); }
}
// 公共方法的实现类
class SwimmingAbility implements Swimmingable {
    @Override
    public void swimming() { System.out.println("游泳"); }
}
// 公共方法的实现类
class EggAbility implements EggLayable {
    @Override
    public void eggLay() {System.out.println("下一颗蛋"); }
}

总结

代码组织结构中经常会出现两类问题:代码层次过深问题,代码不能复用问题

Interface:解决代码层次问题
组合和委托:解决代码复用问题

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值