DAY00

设计模式

什么是设计模式?

他是一套提高代码复用性,健壮性,可读性,安全性的方案

设计模式的分类

  • 按目的
  • 按作用范围

23中设计模式简介

  1. Singleton-单例模式:某个类只能生成一个对象。

  2. Prototype-原型模式:把某个对象作为原型,对其进行复制从而创建出多个与该原型类似新新对象

  3. Factory Method-工厂方法模式:定义一个创建对象的接口,具体生成什么对象,由子类来实现

  4. Abstract Factory-抽象工厂模式:提供一个创建对象族的接口,每个子类可以生成一系列的对象

  5. Builder-建造者模式:将一个复杂的对象分解成多个相对简单的部分,根据不同的需求去创建他们,最后构成该复杂对象

  6. Proxy-代理模式:为对象提供一个种代理来控制对该对象的访问

  7. Bridge-桥接模式:将抽象与实现分离,使他们可以单独变化,降低抽象与实现的耦合度

  8. Adapter-适配器模式:创建一个新类(即适配器类)使得原来接口不兼容不能一起工作的类能一起工作

  9. Dectorator-装饰器模式:动态的为对象添加额外的功能

  10. Factor-外观模式:为多个复杂的子系统提供一个一致的接口,使得这些子系统更加容易被访问

  11. FlyWeight-享元模式:通过共享技术有效的支持大量细粒度对象的复用

  12. Composite-组合模式:将对象组合成树状层次结构,使得单个对象和组合对象的访问具有一致性

  13. TemplateMethod-模板方法模式:定义一个算法框架,将算法的一些步骤延迟到子类,子类可以在不改变该算法结构的前提下,重写算法的一些步骤

  14. Strage-策略模式:定义一组算法,并将每个算法封装,使得他们可以自由切换。

  15. Command-命令模式:将请求封装成一个对象,使得发出请求的责任与执行请求的责任分隔开。

  16. Chain-of-Reposibility-责任链模式:将请求从一个对象传递到另一个对象,知道请求被响应,以此来降低对象间的耦合度。

  17. State-状态模式:一个对象在内部状态改变时改变能够其行为。

  18. Observer-观察者模式:多个对象间存在一对多的关系,当其中一种对象发生改变时,能够将改变通知给其他对象,从而影响其他对象的行为。

  19. Mediator-中介者模式:通过定义一个中介对象来简化原有对象之间的交互关系,降低对象间的耦合度。

  20. Iterator-迭代器模式:提供了一种方法来访问聚合对象中的一系列数据,而不暴露元素的内部表示

  21. Visitor-访问者模式:在不访问集合元素的前提下,为元素提供多种访问方式,即每个元素有多个访问者对象访问。

  22. Memento-备忘录模式:在不破坏对象封装性的前提下,访问并保存对象的内部状态,在需要的时候恢复对象。

  23. Interpreter-解释器模式:提供了如何定义语言的方法,以及如何解释语言子句的方法。

范围\目的创建型模式结构型模式行为型模式
类模式工厂方法(类)适配器模板方法
解释器
对象模式单例
原型
抽象工厂
建造者
代理
(对象)适配器
桥接
装饰
外观
享元
组合
策略
命令
职责链
状态
观察者
中介者
迭代器
访问者
备忘录

类之间的关系

依赖关系

是一种使用关系,是临时性的关联,耦合度最低的一种关系

表现形式

  • 局部变量
  • 方法参数
  • 静态方法调用

表示方法:带箭头的虚线

关联关系

用来表示对象之间的联系,如丈夫-妻子,老师-学生,可以是单向也可以是双向的

表现形式:一个类的对象作为另一个类的成员变量,即成员对象的形式

  • 一般关联关系
    • 表示对象间的联系
    • 表示方法:带箭头的实线
  • 聚合关系
    • 表示对象间是部分与整体的关系,是has-a关系,但是成员对象可以脱离整体对象而独立存在,如学校与老师的关系,学校停办了,老师依旧存在
    • 表示方法:带空心菱形的实线
  • 组合关系
    • 也是表示对象间是部分与整体的关系,是cxmtains-a的关系,整体对象可以控制成员对象的生命周期,但是成员对象不可以脱离整体对象而独立存在,如头和嘴的关系,没有了头,嘴就不存在了
    • 表示方法:带实心菱形的实线
泛化关系

类与类之间耦合度最高一种关系,表示一般与特殊的关系

  • 表现形式:java的继承

  • 表示方法:带空心三角的实线

实现关系

即接口与实现类之间的关系

  • 表示方法:带空心三角的虚线

总结:没有带实心三角的,哈哈

7条常见的原则

口诀:开理依,单结(结)合体(迪)

开闭原则(Open Closed Principle,OCP)

定义:当应用需求发生改变时,在不修改源代码或二进制代码的前提下,扩展模块功能

核心内容:软件实体应该对扩展开放,对修改封闭

软件实体分为三部分

  • 模块
  • 类与接口
  • 方法

实现方式:可以通过“抽象约束,封装变化”的方式来实现开闭原则,通过接口或抽象类为接口定义一个相对稳定的抽象层,而可变因素则是封装在具体的实现类中

作用:

  • 对软件测试的影响:只需要测试拓展的代码即可
  • 提高代码的可复用性:粒度越小,可复用性越大
  • 提高软件的可维护性和稳定性
里氏替换原则(Liskov Substitution Principle,LSP,Liskov:里斯科夫)

定义:继承必须保证基类拥有的特性在派生类仍然成立(像不敢改革的领导)

核心内容:指明了什么时候应该使用继承,什么时候不该使用继承,子类可以扩展父类的功能,但是不能修改父类的功能,如企鹅,鸵鸟从生物学上讲他们都是鸟类,但是他们不能继承鸟类会“飞”的功能。

实现方式:

  • 子类可以扩展父类的功能,但不能修改父类的功能

作用:

  • 里氏替换是实现开闭原则的重要方式之一
  • 克服了继承中重写父类造成可复用性变差的缺点
  • 类的扩展不会给现有系统引入新的错误,即降低代码出错的可能性
依赖倒置原则(Dependence Inversion Principle,DIP)

定义:高层模块不应该依赖于底层模块,两者都应该依赖于其抽象,因为抽象不依赖于其细节,而细节却依赖于抽象。

核心内容:要面向接口编程,不应该面向实现编程,他是开闭原则的重要实现之一,降低了客户和实现模块之间的耦合度

实现方式:

  • 每个类尽量提供接口或抽象类,或者两者都具备。
  • 变量的声明类型尽量是接口或者是抽象类。
  • 任何类都不应该从具体类派生。
  • 使用继承时尽量遵循里氏替换原则。

作用:

  • 降低类之间的耦合度
  • 提高代码的可读性和可维护性
  • 提高系统的稳定性
  • 减少并行开发引起的风险(因为接口和抽象类写好了契约)

例子:

interface Shop {
    void selling();
}

class BeiJingShop implements Shop{
    @Override
    public void selling() {
        System.out.println("北京特产:北京烤鸭,北京酥糖");
    }
}

class ShangHaiShop implements Shop {

    @Override
    public void selling() {
        System.out.println("上海特产:上海水蜜桃,上海浦东鸡");
    }
}

class Cumtomer {
    public void shopping(Shop shop) {
        shop.selling();
    }
}

public class DIP {
    public static void main(String[] args) {
        BeiJingShop beiJingShop = new BeiJingShop();
        ShangHaiShop shangHaiShop = new ShangHaiShop();
        Cumtomer cumtomer = new Cumtomer();
        System.out.println("顾客购买以下商品");
        cumtomer.shopping(beiJingShop);
        cumtomer.shopping(shangHaiShop);
    }
}
//output
顾客购买以下商品
北京特产:北京烤鸭,北京酥糖
上海特产:上海水蜜桃,上海浦东鸡
单一职责原则(Single Responsibility Principle,SRP,又称单一功能原则)

定义:一个类应该有且只有一个引起他变化的原因,否则这个类应该被拆分(即拆分类)

如果一个类承担了太多职责的缺点:

  • 某个职责的变化可能会抑制这个类实现其他职责的能力
  • 客户端只需要某个职责时,不得不将其他职责包含进来,造成冗余代码

实现方式:

  • 根据职责拆分类

作用:

  • 降低代码的复杂度,一个类只负责一个职责
  • 提高提高代码的可读性和可维护性:可读性提高了,可维护性也提高了
  • 变更引起的风险降低,变更是必然的,当修改一个功能时,可以显著的降低对其他功能的影响

例子:学生工作中:生活由辅导员管理,而学业由指导老师管,而不是都丢给其中一个老师

接口隔离原则(Interface Segregation Principle,ISP)

定义:一个类对另一个类的依赖应该建立在最小的接口上(即尽量拆分接口)

实现方式:

  • 接口尽量小,但要有限度,一个接口只服务于一个子模块
  • 了解环境,拒绝盲从,环境不同,接口拆分的原则不同,需要深入了解业务逻辑
  • 为依赖接口的类定制方法,只提供调用者需要的方法

作用:

  • 将臃肿的接口拆分成粒度小的接口,提高系统的灵活性
  • 降低代码的冗余度
  • 提高系统的可读性和可维护性

例子:学生成绩管理程序,分三个接口:录入模块,计算模块,打印模块

合成复用原则(Composite Reuse Principle,CRP)

合成复用又称组合/聚合复用

通常类的复用分:继承复用与组合/聚合复用

继承复用的缺点:

  • 父类子类耦合度高,限制了类的扩展性,父类的任何修改都会导致子类发生发生变化
  • 降低了灵活度,父类继承来的实现都是编译时已确定
  • 破坏了类的封装性,继承会把父类的实现细节暴露给子类

合成复用的优点:

  • 维护了封装性,成员对象的内部细节是不可见的
  • 耦合度降低,整体对象调用成员对象的唯一方法是通过成员对象提供的接口
  • 提高了灵活度,动态的指定成员对象

例子:汽车分类管理程序

迪米特法则(Law of Demeter,LoD)

又名:最少知识原则

定义:如果两个软件实体不发生直接通信,则不应该产生直接相互调用,而应该通过第三方转发调用

作用:

  • 降低耦合度(变成“一般关联”关系,而不是“泛化”关系),提高模块的独立性
  • 提高了独立性意味着可复用性提高

强调的点:

  • 从依赖者的角度,只依赖该依赖的对象
  • 从被依赖者的角度,只暴露该暴露的方法

运用法则的注意事项:

  • 应当创建弱耦合的类
  • 降低成员变量的访问权限
  • 需私有成员的提供访问方法
  • 慎重使用序列化

例子:助理,明星,粉丝,影视公司

class Star {
    private String name;
    public Star(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

class Fan {
    private String name;

    public Fan(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

class Company {
    private String name;
    public Company(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

}
class Agent {
    private Star star;
    private Company company;
    private Fan fan;

    public void setStar(Star star) {
        this.star = star;
    }

    public void setCompany(Company company) {
        this.company = company;
    }

    public void setFan(Fan fan) {
        this.fan = fan;
    }

    public void meeting() {
        System.out.println(star.getName()+" 与 "+fan.getName()+" 见面");
    }

    public void business() {
        System.out.println(star.getName()+" 与 "+company.getName()+" 合作");
    }
}
public class LOD {
    public static void main(String[] args) {
        Agent agent = new Agent();
        agent.setCompany(new Company("唐人影视有限公司"));
        agent.setFan(new Fan("曾小哥"));
        agent.setStar(new Star("唐仁"));
        agent.business();
        agent.meeting();
    }
}
//output
唐仁 与 唐人影视有限公司 合作
唐仁 与 曾小哥 见面
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值