Vampire618


  • 首页

  • 归档

  • 标签

  • 分类

  • 关于

GoF23种设计模式

发表于 2016-10-24   |   分类于 Java   |  

GoF23种设计模式(第一遍读)  

  最近在看一本书,一位大叔给我推荐的《GoF23种设计模式》。以前有听过设计模式这个词,但没有去仔细了解过。只是自己有一个模糊的认识。现在把这本书先过一遍,粗略的记一下笔记。书读三遍,其义自见。这是我的第一遍。   

  • 面向对象系统的分析和设计实际上追求的就是两点:高内聚(Cohension)和低耦合(Coupling)
  • 设计模式是一种思想,其实我们平常开发过程中,已经应用了一些设计模式,不过不知道,哦原来这就是××模式
  • Observer其实例是(Model-View-Control),也就是被说烂了的MVC模式。MVC好像有很多实例。什么Spring MVC之类的。

创建型模式

1.1 Factory模式
问题1:为了提高内聚和低耦合,我们会抽出一些类的公共接口以形成抽象类或者接口。这时候,通过声明一个指向基类的指针来指向实际的子类实现,达到多态的目的。但是当我们要使用一个子类的时候,必须知道子类的名称。然后继承自一个抽象类的子类何其多。子类的名字很难记。程序的扩展性和维护变得越来越困难。
问题2:在父类中不清楚要具体实例化哪一个具体的子类。比如类A中要用到抽象父类B,但是A并不清楚具体要实例化哪一个B的子类。但是在类A的子类D中是可以知道的。所以A中基本上写不出来 new XXX,因为它根本不知道要XXX是什么。

这两个问题也就引出了Factory模式的两个最终呀的功能:

  1. 定义了创建对象的接口,封装了创建对象的过程
  2. 使得具体化类的工作延迟到了子类中(具体做法就是提供一个创建子类的接口,并且在子类中提供具体实现,因为在子类中可以决定到底实例化哪一个类)

总结
  Factory模式对于对象的创建,给予开发人员提供了很好的实现策略,但是Factory模式仅仅局限于同一个基类,如果我们要为不同类的类提供一个对象创建的接口,那就要用AbstractFactory了。
  
1.2 AbstractFactory模式
问题:比如我现在要做一款游戏,里面有各种级别的怪物,初级,中级,高级怪物。而他们都继承自怪物这个类。那也就是说在这个系统中,成千上万的怪物实例都要基于怪物这个类,而保证不会出错。

AbstractFactory模式是用来解决这类问题的:要创建一组相关或相互依赖的对象。
而AbstractFactory模式的关键就是将这一组对象的创建封装到一个用于创建对象的类(ConcreteFactory)中,维护这样一个创建类总比维护n多相关对象的创建过程要简单的多。

注意:初学者容易混淆AbstractoryFacroty模式和Factory模式。实际上,AbstractoryFacroty模式是为了创建一组(有多类)相关或依赖的对象提供创建接口,而Factory模式是为了一类对象提供创建接口,或延迟对象的创建到子类的实现。并且经常可以看到AbstractoryFacroty模式通常是使用Facroty模式实现。

1.3 Singleton模式
问题: Singleton模式要解决的问题是: 我们怎样去创建一个唯一的变量(对象)? 在基于对象的设计中我们可以通过创建一个全局变量来实现。但是在纯粹的面向对象范式中,可能就只能通过Singleton模式来实现了。

Singleton模式是通过维护一个static的成员变量来记录这个唯一的对象的实例。通过提供一个static的接口instance来获得这个唯一的实例。

补充说明: Singleton模式的实现无须补充解释,需要说明的是,Singleton不可以被实例化,因此我们将其构造函数声明为protected或者直接为private

1.4 Builder模式
  当我们要创建的对象很复杂的时候(通常是由其它的对象组合而成),我们要将复杂对象的创建过程和这个对象的表示分离开,这样做的好处就是通过一步步的进行复杂对象的构建,由于在每一步的构造过程中可以引入参数,使得经过相同的步骤创建最后得到的对象的展示不一样。
  讨论
  Builder模式是将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示(通过传入不同的参数)。
  Builder模式和AbstractFactory模式在功能上很相似,都是用来创建复杂的对象,它们的区别是:Builder模式强调的是一步步创建对象,并通过相同的创建过程可以获得不同的结果。一般来说Builder模式中对象不是直接返回的。而在AbstractoryFactory模式强调的是为多个相互依赖的对象提供一个统一的接口。
  
1.5 Prototype模式
Prototype模式提供了一种自我复制的功能,就是说新对象的创建可以通过已有对象进行创建。这个模式提供了一个通过已存在对象进行新对象创建的接口(clone)
讨论
Prototype模式通过复制原型(Prototype)而获得新对象创建的功能,这里的Prototype本身就是“对象工厂”(因为能够生产对象),实际上Prototype模式和Builder模式、AbstractFactory模式重在产生多个相互依赖类的对象,而Prototype模式重在自身复制自己创建新类。

##结构型模式
2.1 Bridge模式
这个Brige模式,表示看不太懂,感觉蛮复杂的。先引述书中的一段描述吧,以后有了理解,再添加进来。

使用组合(委托)的方式将抽象和实现彻底解耦,这样的好处是抽象和实现分别可以独立变化。

2.2 Adapter模式

问题:我们为了完成某项工作购买了一个第三方的库来加快开发。这就带来了一个问题我们在应用程序中的设计好的接口,与第三方提供的接口不一致。为了使这些不兼容的类可以在一起工作,Adapter模式提供了一个类(第三方库接口)转化为客户希望的接口。
上面的解决方式也刚好对应了Adapter模式的两种类别:类模式和对象模式。
在Adapter模式的结构图中可以看到,类模式的Adapter采用继承的方式服用Adaptee的接口,而在对象模式的Adapter中我们则采用组合的方式实现Adaptee复用。

Alt text

讨论
在Adapter模式的两种模式中,有一个很重要的概念就是接口继承和实现继承的区别和联系。接口继承和实现继承是面向对象领域的两个重要的概念,接口继承指的是通过继承子类获得了父类的接口,而实现继承指的是通过继承子类获得了父类的实现(并不统共接口)。

2.3 Decorator模式

问题: 在OO设计和开发过程,可能会经常遇到以下的情况:我们需要为一个已经定义好的类 添加新的职责(操作),通常的情况我们会给定义一个新类继承自定义好的类,这样会带来一个问题(将在本模式的讨论中给出)。通过继承的方式解决这样的情况还带来了系统的复杂性,因为继承的深度会变得很深。

Alt text

Decorator提供了一种给类增加职责的方法,不是通过继承实现的,而是通过组合。在OO设计和分析经常有这样一种情况:为了多态,通过父类指针指向其具体子类,但是这就带来另外一个问题,当具体子类要添加新的职责,就必须向其父类添加一个这个职责的抽象接口,否则是通过父类指针是调用不到这个方法了。这样处于高层的父类就承载了太多的特征(方法),并且继承自这个父类的所有子类都不可避免继承了父类的这些接口,但是可能这并不是这个具体子类所需要的。而在Decorator模式提供了一种较好的解决方法,当需要添加一个操作的时候就可以通过Decorator模式来解决,你可以一步步添加新的职责。

2.4 Composite模式

问题:在开发中,我们经常可能要递归构建树状的组合结构,Composite模式则提供了很好的 解决方案。

Alt text

Composite模式和Decorator模式有着类似的结构图,但是Composite模式旨在构造类,而Decorator模式重在不生成子类即可给对象添加职责。Decorator模式重在修饰,而Composite模式重在表示。

2.5 Flyweight
问题:在面向对象系统的设计何实现中,创建对象是最为常见的操作。这里面就有一个问题: 如果一个应用程序使用了太多的对象,就会造成很大的存储开销。特别是对于大量轻量级(细粒度)的对象。比如在文档编辑器的设计过程中,我们如果为没有字母创建一个对象的话,系统可能会因为大量的对象而造成存储开销的浪费。例如一个字母“a”在文档中出现了100000次,而实际上我们可以让这一万个字母“a”共享一个对象,当然因为在不同的位置可能字母“a”有不同的显示效果(例如字体和大小等设置不同),在这种情况我们可以为将对象的状态分为“外部状态”和“内部状态”,将可以被共享(不会变化)的状态作为内部状态存储在对象中,而外部对象(例如上面提到的字体、大小等)我们可以在适当的时候将外部对象最为参数传递给对象(例如在显示的时候,将字体、大小等信息传递给对象)。

可以从图中看出,Flyweight模式中有一个类似Factory模式的对象构造工厂 FlyweightFactory,当客户程序员(Client)需要一个对象时候就会向FlyweightFactory发出请求对象的消息GetFlyweight()消息,FlyweightFactory拥有一个管理、存储对象的“仓库”(或者叫对象池,vector实现),GetFlyweight()消息会遍历对象池中的对象,如果已经存在则直接返回给Client,否则创建一个新的对象返回给Client。当然可能也有不想被共享的对象(例如结构图中的UnshareConcreteFlyweight

  今天不妨先到这儿,后面的东西在慢慢看,觉得理解了,或者有必要的话再加入进来。说实话,今天写这个设计模式的东西,也就大概了解了前面四五中是什么情况,不过后面写这些其它的模式的时候,有特么忘了。以后再看吧。
感觉严格地讲,写特么这么多(主要是copy),算不算是博客啊?好像有点过于长。不过管他呢,微博不是创新了一下,140个字,就火了。爱长长,爱短短。

markdown学习笔记

发表于 2016-10-18   |   分类于 Blog   |  

markdown学习笔记

1. 标题

一个#号 表示h1标题

例:# 这是h1标题

这是h1标题

两个#号 表示h2标题

例:## 这是h2标题

这是h2标题

以此类推直至 h6标题 那就是6个#号

例:###### 这是h6标题

这是h6标题

2. 特殊字符

在 HTML 文件中,有两个字符需要特殊处理: < 和 & 。如果你要使用它们,需使用它们的原型,&lt 和 &amp 。Markdown 让你可以自然地书写字符,需要转换的由它来处理好了。如果你使用的 & 字符是 HTML 字符实体的一部分,它会保留原状,否则它会被转换成 &amp。

3. 反斜杠

Markdown 可以利用反斜杠来插入一些在语法中有其它意义的符号,例如:如果你想要用星号加在文字旁边的方式来做出强调效果(但不用 <em> 标签),你可以在星号的前面加上反斜杠:
其实文字前后加一个*号或者_,是将文字转为斜体,加入两个的话才是加粗。
*literal asterisks*

literal asterisks

Markdown 支持以下这些符号前面加上反斜杠来帮助插入普通的符号:

\ 反斜线
` 反引号

  • 星号
    _ 底线
    {} 花括号
    [] 方括号
    () 括弧
    # 井字号
  • 加号
  • 减号
    . 英文句点
    ! 惊叹号

4. 代码表示

行内代码用两个 `` 符号括起来。
例:`console.log(“犯我德邦者,虽远必诛!”);`

console.log("犯我德邦者,虽远必诛!");

代码区块只要简单地缩进 4 个空格或是 1 个制表符就可以。不过要注意和上一行之间是隔着一行的。
例:
  这是一个普通段落:

   var canvas = document.getElementById(“canvas”);

这是一个普通段落:

var canvas = document.getElementById("canvas");

或者是使用`

1
2
3
4
5
6
7
8
9
**例:**
\```javascript
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
\

1
2
3
4
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");

5. 区块引用

  • 在每一行文字前面都加入一个<符号,或者在整个段落的第一行加入<号就可以建立一个区块引用。

    This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
    consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
    Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.

  • 区块引用也可以嵌套,只需要在一个引用里面再加入>符号即可。例如:>>This is nested blockquote. 当然其它的Markdown语法(列表、标题)也是可以放进去的。

    1. This is the first level of quoting.

    This is nested blockquote.

    1. Back to the first level.

6. 列表

Markdown 支持有序列表和无序列表。
无序列表使用*、+或是-作为列表标记,有序列表用数字 + 英文点 + 空格 1. 2. 3.表示有序列表

  1. 安妮
  2. 布兰德
  3. 亚索

7. 分割线

你可以在一行中用三个以上的星号、减号、底线来建立一个分隔线,行内不能有其他东西。你也可以在星号或是减号中间插入空格。下面每种写法都可以建立分隔线:

--------------------------------------------------------------------
***
- - -
* * *
___

8. 链接

  Markdown 支持两种形式的链接语法: 行内式和参考式两种形式。要建立一个行内式的链接,只要在方块括号后面紧接着圆括号并插入网址链接即可,如果你还想要加上链接的 title 文字,只要在网址后面,用双引号、单引号或括号把 title 文字包起来即可,例如:This is [an example] (https://vampire618.github.io "vampire618") inline link.

This is an example inline link.

参考式的链接是在链接文字的括号后面再接上另一个方括号,而在第二个方括号里面要填入用以辨识链接的标记:

9. 插入图片

插入图片的形式和链接相似,只需在链接的基础上前方加一个!

![alttext] (http://images.cnitblog.com/blog/404392/201501/122257231047591.jpg)

  • Alt text为如果图片无法显示时显示的文字;
  • /path/to/img.jpg为图片所在路径;
  • Optional title为显示标题。显示效果为在你将鼠标放到图片上后,会显示一个小框提示,提示的内容就是 Optional title 里的内容。
    例:
    Markdown

[参考资料]

  1. AntLog,Markdown你只需要掌握这几个 http://www.cnblogs.com/crazyant007/p/4220066.html
  2. yonghz, Markdown基本语法 https://github.com/younghz/Markdown
  3. riku, Markdown语法简体中文版 http://wowubuntu.com/markdown/

Hello World

发表于 2016-10-15   |  

Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.

Quick Start

Create a new post

1
$ hexo new "My New Post"

More info: Writing

Run server

1
$ hexo server

More info: Server

Generate static files

1
$ hexo generate

More info: Generating

Deploy to remote sites

1
$ hexo deploy

More info: Deployment

Vampire618

Vampire618

我就是我,不一样的水果

3 日志
2 分类
3 标签
GitHub QQ
© 2016 Vampire618
由 Hexo 强力驱动
主题 - NexT.Mist