BillyYccc


  • 首页

  • 关于

  • 标签

  • 分类

  • 归档

设计模式(8):适配器模式ADAPTER

发表于 2017-05-15 | 分类于 DesignPatterns

适配器模式的定义

将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。


使用场景

以下情况使用Adapter模式

  • 你想使用一个已经存在的类,而它的接口不符合你的需求。
  • 你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作。
  • (仅适用于对象Adapter)你想使用一些已经存在的子类,但是不可能对每一个都进行子类化以匹配它们的接口。对象适配器可以适配它的父类接口。

结构

适配器模式分为类适配器和对象适配器两种

类适配器

类适配器模式的结构如下
ShowImage

对象适配器

对象适配器模式的结构如下
ShowImage

  • Target

    – 定义Client使用的与特定领域相关的接口。

  • Client

    – 与符合Target接口的对象交互。

  • Adaptee

    – 定义一个已经存在需要适配的接口。

  • Adapter

    – 将Adaptee的接口适配转换成Target目标接口

协作

Client在Adapter实例上调用一些操作。接着适配器调用Adaptee的操作实现这个请求。

阅读全文 »

Java中深拷贝与浅拷贝

发表于 2017-05-10 | 分类于 Java

深拷贝与浅拷贝

在Java中,有两种方式可以创建对象,第一种是使用new操作符创建对象,第二种是使用clone方法复制一个对象。
下面这段代码创建了magazine2对象并将magazine2的引用指向了magazine1的对象

1
2
3
4
Magazine magazine1 = new Magazine("Times",100);
Magazine magazine2 = magazine1;
System.out.println(magazine1.hashCode());
System.out.println(magazine2.hashCode());

输出结果

1
2
2027961269
2027961269

打印hashCode,发现它们两个对象的hashCode值一样,那么此时它们的地址当然是一样的,其实magazine1和magazine2指向的同一个对象Magazine(“Times”, 100),只不过它们是指向相同对象的两个不同的引用而已。
如下图所示
ShowImage

使用clone()方法复制对象

1
2
3
4
Magazine magazine1 = new Magazine("Times",100);
Magazine magazine2 = (Magazine) magazine1.clone();
System.out.println(magazine1.hashCode());
System.out.println(magazine2.hashCode());

输出结果

1
2
2027961269
1586270964

这次使用clone()方法复制一个对象,打印hashCode不同,这次指向的不是同一个对象了
如下图所示
ShowImage

但是这次拷贝发现,magazine1对象中的String属性name和magazine2对象中的String属性name内容不一样,为什么呢,因为直接实现Cloneable接口重写clone方法这种方式是浅拷贝。

浅拷贝的定义是

使用一个已知实例对新创建实例的成员变量逐个赋值

与浅拷贝对应的是深拷贝

当一个类的拷贝方法,不仅要复制对象的所有非引用成员变量值,还要为引用类型的成员变量创建新的实例,并且初始化为形式参数实例值。

通俗点来说,就是浅拷贝方式只能复制原来实例对象中的基本类型,像int,double这种,不能复制String,List,Map这样的对象类型或者自定义的对象类型。而深拷贝不仅会复制基本类型的值,而且还会复制对象类型的引用比如Book类

1
2
3
4
public class Book {
private String name;
private int page;
}

Book的对象如果使用浅拷贝,那么name值不能复制过去,但是用深拷贝name值也可以复制过去。

但是问题又来了,如果修改下Book类

1
2
3
4
5
public class Book {
private String name;
private int page;
private Bookmark bookmark;
}

增加一个Bookmark的成员

1
2
3
4
public class Bookmark {
private String mark;
private int markPage;
}

现在对Book对象进行复制,bookmark中的String对象mark又不能复制了。这是因为在深拷贝之中只能复制一级引用,好比集装箱一样,浅拷贝不能去复制集装箱里面装的小集装箱,深拷贝可以复制集装箱中的小集装箱,但是如果小集装箱里面还有若干个集装箱,那么此时就无能为力了,想要拷贝就必须再往下一层继续实现深拷贝的方法。所以深拷贝在多级引用上的对象中实现是比较复杂的,要想彻底的深拷贝对象,需要每一级都去实现深拷贝方法。

参考代码

设计模式(7):原型模式PROTOTYPE

发表于 2017-05-10 | 分类于 DesignPatterns

原型模式的定义

用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。


使用场景

当一个系统应该独立于它的产品创建、构成和表示时,并且
• 当要实例化的类是在运行时刻指定时,例如,通过动态装载;或者
• 为了避免创建一个与产品类层次平行的工厂类层次时;或者
• 当一个类的实例只能有少数几个不同状态组合中的一种时。建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些。


结构

原型模式的结构如下
ShowImage

  • Protype

    – 声明一个克隆自身的接口。

  • ConcretePrototype

    – 实现能够克隆自身的操作。

  • Client

    – 通过请求Prototype去克隆自身完成创建一个新的对象的客户端。


协作

客户端请求原型克隆自身

阅读全文 »

设计模式(6):抽象工厂ABSTRACT FACTORY

发表于 2017-05-07 | 分类于 DesignPatterns

抽象工厂模式定义

抽象工厂提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。类图如下
ShowImage

使用场景

在以下情况可以使用Abstract Factory模式

  • 一个系统要独立于它的产品的创建、组合和表示时。
  • 一个系统要由多个产品系列中的一个来配置时。
  • 当你要强调一系列相关的产品对象的设计以便进行联合使用时。
  • 当你提供一个产品类库,而只想显示它们的接口而不是实现时。

结构

  • AbstractFactory

    – 声明一个创建抽象产品对象的操作接口。

  • ConcreteFactory

    – 实现创建具体产品对象的操作。

  • Product

    – 为一类产品对象声明一个接口(或者抽象)。

  • ConcreteProduct

    – 定义一个将被相应的具体工厂创建的产品对象。

    – 实现Product的接口或者继承抽象。

  • Client

    – 仅使用由AbstractFactory和Product类声明的接口。

协作

  • 通常在运行时刻创建一个ConcreteFactory类的实例。这一具体的工厂创建具有特定实现的产品对象。为创建不同的产品对象,客户应使用不同的具体工厂。
  • AbstractFactory将产品对象的创建延迟到它的ConcreteFactory子类。
阅读全文 »

设计模式(5):简单工厂模式

发表于 2017-05-06 | 分类于 DesignPatterns

简单工厂模式

简单工厂模式并不属于GoF归纳的23个经典的设计模式,更像是工厂方法模式(Factory Method Pattern)的一种变体。简单工厂模式又称为静态工厂方法(Static Factory Method)模式,也用于对象的创建。

使用场景

上一节介绍了工厂方法模式,但是有时候并不需要那么多工厂生产,可能只需要一个工厂类就足够了,这个时候我们可以修改一下工厂方法模式中的结构,去掉抽象工厂类,只要一个具体的工厂,并将工厂中的生产方法设置成静态类型的,就可以满足我们新的需求。

简单工厂模式实现(Implement)

结构

按照上面所说,对工厂方法模式的结构进行修改,结构如下
ShowImage

  • Shape

    – Product的抽象类

  • Circle或者Square等等

    – ConcreteProduct的具体类

  • ShapeFactory

    – 去掉抽象的工厂类,只有这一个工厂

    – 提供静态的CreateShape方法进行生产Product

阅读全文 »

设计模式(4):工厂方法FACTORY METHOD

发表于 2017-05-03 | 分类于 DesignPatterns

工厂方法

工厂方法(Factory Method)也称虚构造器(Virtual Constructor)

意图

定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使一个类的实例化延迟到其子类。

适用性

Use the Factory Method pattern when

  • a class can’t anticipate the class of objects it must create.(一个类不知道它所需要的对象的类,也就是说,不需要知道具体产品的类名,只需要知道创建它的具体工厂就行了)
  • a class wants its subclasses to specify the objects it creates.(一个类通过子类来指定所要创建的对象,抽象工厂类只提供创建产品的接口,由子类来确定要创建的具体的对象,充分利用多态的特性,运行时子类对象替换父类对象)
  • classes delegate responsibility to one of several helper subclasses, and you want to localize the knowledge of which helper subclass is the delegate.(将创建对象的任务委托给多个工厂子类中的一个,这样使用时就不用关心到底是哪一个工厂子类创建产品子类,需要的时候动态指定就可以了)
阅读全文 »

设计模式(3):建造者模式BUILDER

发表于 2017-04-30 | 分类于 DesignPatterns

建造者模式定义

意图

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

适用性

在以下情况使用Builder模式

  • 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。
  • 当构造过程必须允许被构造的对象有不同的表示时。
阅读全文 »

设计模式(2):单例模式SINGLETON

发表于 2017-04-28 | 分类于 DesignPatterns

单例模式定义

单例模式(Singleton pattern)限制了类的实例化,并且确保了该类有且仅有一个实例存在。单例类必须提供一个获取实例的全局入口点(global access point)。单例模式类图如下
ShowImage

使用场景

单例模式在应用程序中的使用还是很广的,比如应用的日志管理应用、数据库连接池、线程池等等,这些都应该只有一个实例去操作。

单例模式的实现由以下几个要点:

  • 私有的构造器保证其他类不能对单例类进行实例化
  • 私有的静态变量确保该类只有一个实例
  • 返回该类实例的公有的静态方法,提供给其他类获取单例的接口
阅读全文 »

设计模式(1)

发表于 2017-04-27 | 分类于 DesignPatterns

设计模式

Christopher Alexander 说过:“每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心。这样,你就能一次又一次地使用该方案而不必做重复劳动”。尽管Alexander所指的是城市和建筑模式,但他的思想也同样适用于面向对象设计模式,只是在面向对象的解决方案,我们用对象和接口代替了墙壁和门窗。两类模式的核心都在于提供了相关问题的解决方案。

一般而言,一个模式有四个基本要素:

  • 模式名称(pattern name)

一个助记名,它用一两个词来描述模式的问题、解决方案和效果。命名一个新的模式增加了我们的设计词汇。设计模式允许我们在较高的抽象层次上进行设计。基于一个模式词汇表,我们自己以及同事之间就可以讨论模式并在编写文档时使用它们。模式名可以帮助我们思考,便于我们与其他人交流设计思想及设计结果。找到恰当的模式名也是我们设计模式编目工作的难点之一。

  • 问题(problem)

描述了应该在何时使用模式。它解释了设计问题和问题存在的前因后果,它可能描述了特定的设计问题,如怎样用对象表示算法等。也可能描述了导致不灵活设计的类或对象结构。有时候,问题部分会包括使用模式必须满足的一系列先决条件。

  • 解决方案(solution)

描述了设计的组成成分,它们之间的相互关系及各自的职责和协作方式。因为模式就像一个模板,可应用于多种不同场合,所以解决方案并不描述一个特定而具体的设计或实现,而是提供设计问题的抽象描述和怎样用一个具有一般意义的元素组合(类或对象组合)来解决这个问题。

  • 效果(consequences)

描述了模式应用的效果及使用模式应权衡的问题。尽管我们描述设计决策时,并不总提到模式效果,但它们对于评价设计选择和理解使用模式的代价及好处具有重要意义。软件效果大多关注对时间和空间的衡量,它们也表述了语言和实现问题。因为复用是面向对象设计的要素之一,所以模式效果包括它对系统的灵活性、扩充性或可移植性的影响,显式地列出这些效果对理解和评价这些模式很有帮助。

阅读全文 »

面向对象的六大原则(六)

发表于 2017-04-22 | 分类于 DesignPatterns

迪米特原则的定义

迪米特法则(Law of Demeter,LoD)也称为最少知识原则(Least Knowledge Principle,LKP),虽然名字不同,但描述的是同一个规则:(一个对象应该对其他对象有最少的了解)。通俗地讲,一个类应该对自己需要耦合或调用的类知道得最少,你(被耦合或调用的类)的内部是如何复杂都和我没关系,那是你的事情,我就知道你提供的这么多public方法,我就调用这么多,其他的我一概不关心。

总结起来就是以下三点:

  • Each unit should have only limited knowledge about other units: only units “closely” related to the current unit.(每个单元对于其他的单元只能拥有有限的知识:只是与当前单元紧密联系的单元。)
  • Each unit should only talk to its friends; don’t talk to strangers.(每个单元只能和它的朋友交谈:不能和陌生单元交谈。)
  • Only talk to your immediate friends.(只和自己直接的朋友交谈。)
阅读全文 »
1…345
Billy Yuan

Billy Yuan

48 日志
6 分类
15 标签
GitHub E-Mail Twitter
© 2018 Billy Yuan
由 Hexo 强力驱动
|
主题 — NexT.Muse v5.1.3