• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 众包
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

无信不立

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

【重温设计模式】面向对象,面向过程编码

一、为什么要学习设计模式

1、为什么学习设计模式

  • 数据结构与算法之美”让你写出高效的代码,那这个设计模就是让你写出高质量的代码。
  • 告别写被人吐槽的烂代码
  • 提高复杂代码的设计和开发能力
  • 让读源码、学框架事半功倍
  • 为你的职场发展做铺垫

2、好的代码标准

1. 可维护性(maintainability)

  • 所谓“代码易维护”就是指,在不破坏原有代码设计、不引入新的 bug 的情况下,能够快速地修改或者添加代码。所谓“代码不易维护”就是指,修改或者添加代码需要冒着极大的引入新 bug 的风险,并且需要花费很长的时间才能完成。

2. 可读性(readability)

  • 代码是否符合编码规范、命名是否达意、注释是否详尽、函数是否长短合适、模块划分是否清晰、是否符合高内聚低耦合等等。

3. 可扩展性(extensibility)

  • 表示我们的代码应对未来需求变化的能力。跟可读性一样,代码是否易扩展也很大程度上决定代码是否易维护。
  • 代码的可扩展性表示,我们在不修改或少量修改原有代码的情况下,通过扩展的方式添加新的功能代码。说直白点就是,代码预留了一些功能扩展点,你可以把新功能代码,直接插到扩展点上,而不需要因为要添加一个功能而大动干戈,改动大量的原始代码。
  • 关于代码的扩展性,在后面讲到“对修改关闭,对扩展开放”这条设计原则的时候。

4. 灵活性(flexibility)

  • 当我们添加一个新的功能代码的时候,原有的代码已经预留好了扩展点,我们不需要修改原有的代码,只要在扩展点上添加新的代码即可。这个时候,我们除了可以说代码易扩展,还可以说代码写得好灵活。
  • 当我们要实现一个功能的时候,发现原有代码中,已经抽象出了很多底层可以复用的模块、类等代码,我们可以拿来直接使用。这个时候,我们除了可以说代码易复用之外,还可以说代码写得好灵活。
  • 当我们使用某组接口的时候,如果这组接口可以应对各种使用场景,满足各种不同的需求,我们除了可以说接口易用之外,还可以说这个接口设计得好灵活或者代码写得好灵活。

5. 简洁性(simplicity)

  • 思从深而行从简,真正的高手能云淡风轻地用最简单的方法解决最复杂的问题。这也是一个编程老手跟编程新手的本质区别之一。
  • 代码要尽量写得简洁,符合 KISS 原则:(待补充)

 

6. 可复用性(reusability)

  • 简单地理解为,尽量减少重复代码的编写,复用已有的代码。
  • 解耦、高内聚、模块化等都能提高代码的可复用性;
  • 单一职责原则也跟代码的可复用性相关;
  • 继承、多态存在的目的之一,就是为了提高代码的可复用性
  • DRY 设计原则

7. 可测试性(testability)

  • 代码可测试性的好坏,能从侧面上非常准确地反应代码质量的好坏。代码的可测试性差,比较难写单元测试,那基本上就能说明代码设计得有问题。关于代码的可测试性,我们在重构那一部分,会花两节课的时间来详细讲解。现在,你暂时只需要知道,代码的可测试性非常重要就可以了。 

二、面向对象

1、面向对象四大特性

  • 封装
  • 抽象
  • 继承
  • 多态

(1)封装

  • 定义:封装也叫作信息隐藏或者数据访问保护。类通过暴露有限的访问接口,授权外部仅能通过类提供的方式(或者叫函数)来访问内部信息或者数据
  • 意义和价值:信息隐藏或者数据访问保护,对类的数据访问进行限制,保证类的数据的可控性;类仅仅通过有限的方法暴露必要的操作,也能提高类的易用性;(电视和电冰箱就几个按钮,内部实现很复杂)

(2)抽象

  • 定义:如何隐藏方法的具体实现,让调用者只需要关心方法提供了哪些功能,并不需要知道这些功能是如何实现的。
  • 意义和价值:抽象作为一个非常宽泛的设计思想,在代码设计中,起到非常重要的指导作用。很多设计原则都体现了抽象这种设计思想,比如基于接口而非实现编程、开闭原则(对扩展开放、对修改关闭)、代码解耦(降低代码的耦合性);一方面是提高代码的可扩展性、维护性,修改实现不需要改变定义,减少代码的改动范围;另一方面,它也是处理复杂系统的有效手段,能有效地过滤掉不必要关注的信息;

(3)继承

  • 定义:继承是用来表示类之间的 is-a 关系,比如猫是一种哺乳动物。从继承关系上来讲,继承可以分为两种模式,单继承和多继承。单继承表示一个子类只继承一个父类,多继承表示一个子类可以继承多个父类,比如猫既是哺乳动物,又是爬行动物。
  • 意义和价值:继承最大的一个好处就是代码复用;继承这个特性也是一个非常有争议的特性。很多人觉得继承是一种反模式。我们应该尽量少用,甚至不用。“多用组合少用继承”这种设计思想;

(4)多态

  • 定义:多态是指,子类可以替换父类,在实际的代码运行过程中,调用子类的方法实现
  • 意义和价值:多态提高了代码的可扩展性。多态也是很多设计模式、设计原则、编程技巧的代码实现基础,比如策略模式、基于接口而非实现编程、依赖倒置原则、里式替换原则、利用多态去掉冗长的 if-else 语句等等

 

2、六大设计原则

  • SOLID 原则 -SRP 单一职责原则
  • SOLID 原则 -OCP 开闭原则
  • SOLID 原则 -LSP 里式替换原则
  • SOLID 原则 -ISP 接口隔离原则
  • SOLID 原则 -DIP 依赖倒置原则
  • DRY 原则、KISS 原则、YAGNI 原则、LOD 法则

3、23种设计模式

1. 创建型

  • 常用的有:单例模式、工厂模式(工厂方法和抽象工厂)、建造者模式。
  • 不常用的有:原型模式。

2. 结构型

  • 常用的有:代理模式、桥接模式、装饰者模式、适配器模式。
  • 不常用的有:门面模式、组合模式、享元模式。

3. 行为型

  • 常用的有:观察者模式、模板模式、策略模式、职责链模式、迭代器模式、状态模式。
  • 不常用的有:访问者模式、备忘录模式、命令模式、解释器模式、中介模式。

 

4、重构

  • 重构的目的(why)、对象(what)、时机(when)、方法(how);
  • 保证重构不出错的技术手段:单元测试和代码的可测试性;
  • 两种不同规模的重构:大重构(大规模高层次)和小重构(小规模低层次)。

三、面向对象编程的指导思想和原则

1、什么是面向对象编程

  • 面向对象编程是一种编程范式或编程风格。它以类或对象作为组织代码的基本单元,并将封装、抽象、继承、多态四个特性,作为代码设计和实现的基石 。

2、抽象类和接口

  • 抽象类:表示类之间的 is-a 关系,不能被实力化,解决代码复用问题,同时保持多态特性。  自下而上的行为,先发现子类逻辑重复,再抽象到抽象类。
  • 接口:表示解藕,对行为的抽象,基于接口而非实现的编程思想。提高程序的可扩展性,和灵活性。自上而下的设计行为,先定义规则,再去实现。

3、接口(面向接口而非实现编程思想)

  • 接口是一组协议,或者约定。是功能提供者提供给使用者的一组功能列表。
  • 将接口和实现分离,封装不稳定的实现,暴露稳定的接口给上游系统,上游系统面向稳定的接口而非实现编程,不依赖不稳定的实现细节,当实现发生变化时,上游系统不用改动,以此降低耦合性,提高代码扩展性。
  • 接口的定义,要抽象,共性,不要有特殊性的定义。

4、多用组合少用继承

(1)继承

  • 继承最大的问题就在于:继承层次过深、继承关系过于复杂会影响到代码的可读性和可维护性。这也是为什么我们不推荐使用继承;
  • 如果类之间的继承结构稳定(不会轻易改变),继承层次比较浅(比如,最多有两层继承关系),继承关系不复杂,我们就可以大胆地使用继承。

 

(2)组合

  • 利用组合(composition)、接口、委托(delegation)三个技术手段,一块儿来解决刚刚继承存在的问题。
  • 继承层次深,且容易变化,利用组合还能解决层次过深、过复杂的继承关系影响代码可维护性的问题。

 

基于继承实现的代码示意

/**
 * 会吃的鸟
 */
abstract class AbstractBird {

    abstract void eat();
}

/**
 * 会吃,会飞,会下蛋的鸟
 */
abstract class AbstractFlyAndEggBird extends AbstractBird {
    abstract void fly();

    abstract void egg();
}

/**
 * 会吃,会叫,会游泳的鸟
 */
abstract class AbstractTweetAndSwimBird extends AbstractBird {
    abstract void tweet();

    abstract void swim();
}


/**
 * 鸡
 */
class Chicken extends AbstractFlyAndEggBird {

    @Override
    void eat() {
        System.out.println("吃东西");
    }

    @Override
    void fly() {
        System.out.println("飞");
    }

    @Override
    void egg() {
        System.out.println("下蛋");
    }
}

/**
 * 鸭
 */
class Duck extends AbstractTweetAndSwimBird {

    @Override
    void eat() {

        System.out.println("吃东西");
    }

    @Override
    void tweet() {
        System.out.println("叫");
    }

    @Override
    void swim() {
        System.out.println("游泳");
    }
}
View Code

基于组合实现的代码示意(组合、接口、委托)

/**
 * 吃
 */
interface Eat {

    void eat();
}

/**
 * 飞
 */
interface Fly {

    void fly();
}

/**
 * 下蛋
 */
interface Egg {

    void egg();
}

/**
 * 叫
 */
interface Tweet {

    void tweet();
}

/**
 * 游泳
 */
interface Swim {

    void swim();
}


class Earter implements Eat {

    @Override
    public void eat() {
        System.out.println("吃");
    }
}

class FlyEr implements Fly {

    @Override
    public void fly() {
        System.out.println("飞");
    }
}

class Egger implements Egg {
    @Override
    public void egg() {
        System.out.println("下蛋");
    }
}

class TweetEr implements Tweet {
    @Override
    public void tweet() {
        System.out.println("叫");
    }
}

class SwimEr implements Swim {
    @Override
    public void swim() {
        System.out.println("游泳");
    }
}


/**
 * 鸡
 */
class Chicken1 implements Eat, Fly, Egg {

    private Eat eat = new Earter();
    private Fly fly = new FlyEr();
    private Egg egg = new Egger();

    @Override
    public void eat() {
        eat.eat();
    }

    @Override
    public void fly() {
        fly.fly();
    }

    @Override
    public void egg() {
        egg.egg();
    }
}

/**
 * 鸭
 */
class Duck1 implements Eat, Tweet, Swim {

    private Eat eat = new Earter();
    private Tweet tweet = new TweetEr();
    private Swim swim = new SwimEr();

    @Override
    public void eat() {
        eat.eat();
    }

    @Override
    public void tweet() {
        tweet.tweet();
    }

    @Override
    public void swim() {
        swim.swim();
    }
}
View Code

 

posted on 2020-07-12 18:29  无信不立  阅读(156)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3