【读书笔记】Head First 设计模式 读书笔记

  • 设计原则:找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起
  • 设计原则:针对接口编程,而不是针对实现编程
  • 设计原则:多用组合,少用继承
  • 设计原则:为了交互对象之间的松耦合设计而努力
  • 设计原则:类应该对扩展开放,对修改关闭
  • 设计原则:要依赖抽象,不要依赖具体类
    • 变量不可以持有具体类的引用
    • 不要让类派生自具体类
    • 不要覆盖基类中已实现的方法
  • 设计原则:最少知识原则:减少对象之间的交互,只留下几个“密友”,只和你的密友谈话
    • 一个对象的方法内,我们只应该调用属于一下范围的方法:
      • 该对象本身
      • 被当做方法的参数而传递进来的对象
      • 此方法所创建或实例化的任何对象
      • 对象的任何组件
  • 设计原则:好莱坞原则:别调用我们,我们会调用你。高层组件绝对不可以直接调用高层组件
  • 设计原则:一个类应该只有一个引起变化的原因。这个原则告诉我们,尽量让每个类保持着单一责任。类的每个责任都有改变的潜在区域。超过一个责任,意味着超过一个改变的区域。

  • 设计模式:策略模式:定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
  • 设计模式:观察者模式:定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
    • Subject:主题的接口,对象使用此接口注册为观察者,或者把自己从观察者中删除
    • ConcreteSubject:一个具体主题总是实现主题接口,除了注册和撤销方法之外,具体主题还实现了notify()方法,此方法用于在状态改变时更新所有当前的观察者
    • Observer:所有潜在的观察者必须实现观察者接口,这个接口只有update一个方法,当主题状态改变时它被调用
    • ConcreteObserver:具体的观察者可以是实现此接口的任意类。观察者必须注册具体主题,一边接收更新。
    • 两种机制:
      • 当有subject数据变化时,subject传递数据给observer,observer被动接受
      • 当有subject数据变化时,subject通知observer数据已经改变,observer自己来请求数据
    • java中有内置的java.util.Observer的接口以及java.util.Observable类,Observable类中有的方法有:
      • setChanged()来指示数据已经改变
      • notifyObservers()来向观察者传递数据或者直接提醒他们数据改变
      • addObserver(Observer)来向观察者链条中添加观察者
    • 优点:
      • 改变的是主题的状态,以及观察者的数目和类型。用这个模式,可以改变依赖于主题的对象,却不必改变主题
      • 主题和观察者都是用接口,观察者利用主题的接口向主题注册,而主题利用观察者的接口通知观察者,这样可以让两者之间运作正常,又同时具有松耦合
      • 观察者模式利用组合将许多观察者组合进主题中,对象之间的这种关系不是通过继承产生的,而是在运行时利用组合的方式而产生的
  • 设计模式:装饰者模式:动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案
    • java的IO就是使用装饰者模式
    • Component: 组件类,每个组件都可以单独使用或者被装饰者包起来使用
    • ConcreteComponent:是我们将要动态的加上新行为的对象,扩展自Component
    • Decorator:装饰者类,每个装饰者都有一个(包装一个)组件,也就是说,装饰者有一个实例变量以保存某个Component的引用;为装饰者共同实现的接口或抽象类
    • ConcreteDecorator:有一个实例变量,可以记录所有所装饰的事务,装饰者包着Component;装饰者可以扩展Component状态;装饰者可以加上新的方法。新行为是通过在旧行为前面或后面做一些计算来添加的
  • 设计模式: 工厂方法模式:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
    • Product:所有产品必须实现这个共同的接口,这样一来,使用这些产品的类就可以引用这个接口,而不是具体类
    • ConcreteProduct:具体的产品类,实现了Product接口
    • Creator:一个类,它实现了所有操纵产品的方法,但不实现工厂方法;Creator的所有子类都必须实现其FactoryMethod()方法
    • ConcreteCreator:实现了Creator的FactoryMethod()方法,以实际制造出产品;它负责创建一个活多个具体产品,只有ConcreteCreator类知道如何创建这些产品
  • 设计模式: 抽象工厂模式:提供了一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
    • AbstractFactory:抽象工厂定义了一个接口,所有的具体工厂都必须实现此接口,这个接口包含一组方法用来生产产品
    • ConcreteFactory1  ,  ConcreteFactory2 :具体工厂类,具体工厂实现不同的产品家族。要创建一个产品,客户只要使用其中的一个工厂而完全不需要实例化任何产品对象。
    • Client:客户的代码中只需涉及抽象工厂,运行时将自动使用实际的工厂
    • AbstractProductA , AbstractProductB:产品家族,每个具体工厂都能产生一整组的产品
  • 设计模式:单件模式:确保一个类只有一个实例,并提供一个全局访问点。
    • uniqueInstance:持有唯一的单件实例,为static变量
    • Singleton:单件模式的类也可以是一般的类,具有一般的数据方法
    • Intance():方法时静态的,意味着这是一个类的方法,所以可以在代码的任何地方使用Singleton.Instance()方法访问它,这和访问全局变量一样简单,只是多了一个优点:单件可以延迟实例化
    • 经典的单件模式实现:
      • public class Singleton {
      • private static Singleton uniqueInstance;
      • private Singleton() {}
      • public static Singleton getInstance() {
      • if (uniqueInstance == null){
      • uniqueInstance = new Singleton();
      • }
      • return uniqueInstance;
      • }
      • }
    • 使用static初始化:
      • public class Singleton {
      • private static Singleton uniqueInstance = new Singleton();
      • public static Singleton getInstance () {
      • return uniqueInstance;
      • }
      • }
    • 用双重检查加锁:
      • public class Singleton {
      • private volatile static Singleton uniqueInstance;
      • private Singleton() {}
      • public static Singleton getInstance() {
      • if(uniqueInstance == null){
      • synchronized(Singleton.class){
      • if(uniqueInstance == null){
      • uniqueInstance = new Singleton();
      • }
      • }
      • }
      • return uniqueInstance;
      • }
      • }
    • 如果有两个以上的类加载器,不同的类加载器可能会加载同一个类,从整个程序来看,同一个类会被加载很多次
    • 单例的构造器为私有
  • 设计模式:命令模式: 将“请求”封装成对象,以便使用不同的请求,队列或者日志来参数化其他对象,命令模式也支持可撤销的操作。
    • Client:这个客户负责创建一个ConcreteCommand,并设置其接收者
    • Invoker:这个调用者持有一个命令对象,并在某个时间点调用命令对象的execute()方法,将请求付诸实行
    • Command:Command为所有命令声明了一个接口。调用命令对象的execute()方法,就可以让接收者进行相关的动作。这个接口也具备一个undo()方法
    • Receiver:接收者知道如何进行必要的工作。
    • ConcreteCommand:这个ConncreteCommand定义了动作和接收者之间的绑定关系。调用者只要调用execute()就可以发出请求,然后由ConcreteCommand调用接收者的一个或多个动作
    • execute()方法会调用接收者的动作,以满足请求
    • 可以使用宏命令:在一个ConcreteCommand中创建一个Command的序列Command[] commands,execute()方法改为执行commands序列中的所有方法
    • 在command中可以定义undo()方法,使用一个堆栈记录操作的过程的每个命令,然后不管什么时候撤销,都可以取出栈中最上层的命令,调用其undo()方法
  • 设计模式:适配器模式:将一个类的接口,转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。
    • 对象适配器
    • Client:客户只能看到目标接口
    • Adapter:适配器实现目标接口
    • Adaptee:所有的请求都委托给被适配者
    • Target: 定义Client使用的与特定领域相关的接口

    • 类适配器
    • 类适配器不是使用组合来适配被适配者,而是继承被适配者和目标类
    • 被适配者的任何子类,都可以搭配着适配器使用
    • 对象适配器和类适配器的对比:
      • 对象适配器使用组合,可以适配某个类,也可以适配该类的任何子类;类适配器不需要重新实现整个被适配者
  • 设计模式:外观模式:提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。
    • Facade:统一的接口易于使用,用于被客户调用的接口
    • 外观模式将客户从一个复杂的子系统中解耦
  • 设计模式: 模板方法模式:在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
    • AbstractClass:这个模板方法所用到的操作的抽象版本,这个抽象类包含了模板方法
    • ConcreteClass:可能有许多个具体类,每一个类都实现了模板方法所需的全部操作,当模板方法需要这两个抽象方法时会调用他们
    • PrimitiveOperation1()   ....:模板方法在实现算法的过程中,用到了这两个原语操作。模板方法本身和这两个操作的具体实现之间被解耦了
    • 钩子是一种被声明在抽象类中的方法,但只有空的或者默认的实现,钩子的存在,可以让子类有能力对算法的不同点进行挂钩。要不要挂钩,由子类决定。当算法的这个部分是可选的,就使用钩子
      • 钩子可以让子类能够有机会对模板中的某些即将发生的步骤做出反应
      • 钩子可以让子类有能力为其抽象类做一些决定
  • 设计模式: 迭代器模式:提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。
    • 把游走的任务放在迭代器上,而不是聚合上。这样简化了聚合的接口和实现,也让责任各得其所
    • Aggregate:有一个共同的接口供所有的聚合使用,这对客户代码是很方便的,将客户代码从集合对象的实现解耦
    • Iterator:这是所有迭代器都必须实现的接口,它包含了一些方法,利用这些方法可以在集合元素之间游走。在这个,我们使用的是java.util.Iterator,如果不想使用java的迭代器,也可以自己设计一个接口
    • ConcreteAggregate:这个具体聚合持有一个对象的集合,并实现一个方法,利用此方法返回集合的迭代器,每一个具体聚合都要负责实例化一个具体迭代器,此迭代器能够遍历对象集合
    • ConcreteIterator:这个具体迭代器负责管理目前遍历的位置
    • java.util.Iterator接口:有三个方法:hasNext(),next(),remove()
    • 迭代器模式实现的是“外部迭代器”;“内部迭代器”则是由迭代器自己控制,在这种情况下,因为是有迭代器自行在元素之间游走,所以你必须告诉迭代器在游走过程中,要做些什么事情,也就是说,你必须将操作传入给迭代器。因为客户无法控制便利过程,所以内部迭代器比外部迭代器更没有弹性。
  • 设计模式:组合模式:允许你将对象组合成树形结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象以及对象组合。
    • 组合模式让我们能用属性的方式创建对象的结构,树里面包含了组合以及个别的对象。
    • 使用组合结构,我们能把相同的操作应用在组合和个别对象上。换句话说,在大多数情况下,我们可以忽略对象组合和个别对象之间的差别。
    • Client:客户,客户使用Component接口操作组合中的对象
    • Component:组合中所有对象定义一个接口,不管是组合还是叶节点,可以为add()、remove()、getChild()和它的操作实现一些默认行为
    • Leaf:叶节点,叶节点没有孩子,通过实现Composite支持的操作,定义了组合内的元素行为。叶节点也继承了像add()、remove()和getChild()方法,这些方法对叶节点或许没有意义。
    • Composite:定义组件的行为,这样的组件具有子节点。
    • 空迭代器:两种选择:
      • 返回null,可以让createIterator()方法返回null,但是若这么做,客户代码需要条件语句来判断返回值是否为null
      • 返回一个迭代器,而这个迭代器的hasNext()方法永远返回false
    • 可以将迭代器模式和组合模式结合在一起
  • 设计模式:状态模式:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类
    • Context:上下文,一个类,他可以拥有一些内部状态
    • State:state接口定义了一个所有具体状态的共同接口;任何状态都实现这个相同的接口,这样一来,状态直接可以互相替换。
    • state->Handle():不管是在什么时候,只要有人调用Context的request()方法,它就会被委托到状态来处理
    • ConcreteState:具体状态,处理来自Context的请求。每一个ConcreteState都提供了它自己对于请求的实现。所以,当Context改变状态时行为也跟着改变。具体的状态可以有很多
  • 设计模式:代理模式:为另一个对象提供一个替身货占位符以控制对这个对象的访问
    • 使用代理模式创建代表对象,让代表对象控制某对象的访问,被代理的对象可以是远程的对象、创建开销的大的的对象或需要安全控制的对象
    • Subject:Proxy和RealSubject都实现了Subject接口,这允许任何客户都可以像处理RealSubject对象一样地处理proxy对象
    • RealSubject:通常是真正做事的对象,proxy会控制对RealSubject的访问
    • Proxy:持有对RealSubject对象的引用,所以必要时它可以将请求转发给Subject。创建RealSubject对象,通常由proxy负责
    • 可能的运行时的对象持有图:
    • java在java.lang.reflect包中有自己的代理支持,可以在运行时动态地创建一个代理类。我们称这个Java技术为:动态代理
    • 动态代理之所以被称为动态,因为运行时才将它的类创建出来。代码开始执行时,还没有proxy类,它是根据需要从你传入的接口集创建
  • 复合模式:模式通常被一起使用,并被组合在一个设计解决方案中。复合模式在一个解决方案中结合两个或多个模式,以解决一般或重复发生的问题。
  • MVC
    • M:module:模型:模型持有所有数据、状态和程序逻辑。模式诶有注意到视图和控制器,虽然它提供了操纵和检索状态的接口,并发送状态改变通知给观察者。
    • V:viewer:视图:用来呈现模型。视图通常直接从模型中取得它需要显示的状态和数据。
    • C:controller:控制器:取得用户的输入并解读其对模型的意思
    • MVC中的设计模式:
      • 策略模式:视图和控制器实现了经典的策略模式:视图是一个对象,可以被调整使用不同的策略,而控制其提供了策略。视图只关心系统中的可视部分,对于任何界面行为,都委托给控制器处理。使用策略模式也可以让视图和模型之间的关系解耦,因为控制器负责和模型交互来传递用户请求。对于工作是怎么完成的,视图毫不知情
      • 观察者模式:模型实现了观察者模式,当状态改变时,相关对象将持续更新。使用观察者模式,可以让模型完全独立于视图和控制器。同一个模型可以使用不同的视图,甚至可以同时使用多个视图。
      • 组合模式:视图中使用了组合模式,每个显示组件如果不是组合节点,就是叶节点。

    • B/S模型
      • 用户发出http请求,Servlet收到这样的数据,并解析数据
      • Servlet:扮演控制器的角色,处理请求,通常会向模型(一般是数据库)发出请求,处理结果往往以JavaBean的形式打包
      • 视图就是JSP,而JSP唯一的工作就是产生页面,表现模型的视图(模型通过JavaBean中获得)以及进一步动作所需要的所有控件
      • 页面返回浏览器,作为视图显示出来。用户提出进一步的请求,以同样的方式进行处理
  • 模式:某情境下,针对某问题的某种解决方案。
    • 情境:应用某个模式的情况。这应该是会不断出现的情况。
    • 问题:想在某个情境下达到目标,但也可以是某情境下的约束
    • 解决方案:一个通用的设计,用来解决约束,达到目标
  • 模式分类
    • 职责分:
      • 创建型:创建型模式涉及到坚固地向实例化,这类模式都提供一个方法,将客户从所需要实例化的对象中解耦
        • 单例(Singleton)、工厂方法(Factory Method)、抽象工厂(Abstract Factory)、原型(Prototype)、生成器(Builder)
      • 结构型:真可以让你把类或对象组合到更大的结构中
        • 装饰者(Decorator)、适配器(Adapter)、组合(Composite)、代理(Proxy)、外观(Facade)、桥接(Bridge)、享元(Flyweight)
      • 行为型:涉及到类和对象如何交互及分配职责
        • 模板方法(Template Method)、命令(Command)、迭代器(Iterator)、观察者(Observer)、状态(State)、策略(Strategy)、解释器(Interpreter)、职责连(Chain of Responsibility)、备忘录(Memento)、中介者(Mediator)、访问者(Visitor)
    • 按照模式所处理的是类或对象:
      • : 类模式描述类孩子间的关系如果通过继承定义。类模式的关系是在编译时建立的
        • 模板方法(Template Method)、 工厂方法(Factory Method)、 适配器(Adapter)、 解释器(Interpreter)
      • 对象:对象模式描述对象之间的关系,而且主要是利用组合定义。对象模式的关系通常在运行时建立,而且更加动态,更有弹性
        • 其他
  • 其他设计模式:
    • 桥接:使用桥接模式不只改变实现,也改变抽象。桥接模式通过将实现和抽象放在两个不同的类层次中而使它们可以独立改变。
    • 生成器:封装一个产品的构造过程,并允许按步骤构造
    • 责任链:让一个以上的对象有机会能够处理某个请求
    • 蝇量:让某个类的一个实例能用来提供许多”虚拟实例“
    • 解释器:为语言创造解释器
    • 中介者:集中相关对象之间复杂的沟通和控制方式
    • 备忘录:当你需要让对象返回之前的状态
    • 原型:当创建给定类的实例的过程很昂贵或很复杂时使用
    • 访问者:想要为一个对象的组合增加新的能力,且封装并不重要时使用
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值