`
maosheng
  • 浏览: 547684 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

设计模式(Design Patterns)

 
阅读更多

1.面向对象基本概念【OO(Object-Oriented) Basics】

抽象(Abstraction)

封装(Encapsulation)

继承(Inheritance)

多态(Polymorphism)

 

2. Design Principle 1

 

找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起(封装变化点)

 

把会变化的部分取出并“封装”起来,以便以后可以轻易地修改或扩充此部分,而不影响不需要变化的其他部分

 

Identify the aspects for your application that vary and separate them from what stays the same.

Here's another way to think about this principle:

take the parts that vary and encapsulate them,so that later you can alter or extend the parts that vary without affecting those that don't

 

 

3. Design Pinciple 2

 

针对接口编程,而不是针对实现编程

 

”针对接口编程“真正的意思是“针对超类型(supertype)编程”

 

这里所谓的“接口”有多个含义,接口是一个“概念”,也是一种Java的interface构造。你可以在不涉及Java interface的情况下,“针对接口编程”,关键就在多态。利用多态,程序可以针对超类型编程,执行时会根据实际状况执行到真正的行为,不会被绑死在超类型的行为上。“针对超类型编程”这句话,可以更明确地说成“变量的声明类型应该是超类型,通常是一个抽象类或者是一个接口,如此,只要是具体实现此超类型的类所产生的对象,都可以指定给这个变量。这也意味着,声明类时不用理会以后执行时的真正对象类型!”

 

Program to an interface,not an implementation

 

"Program to an interface" really means "Program to a supertype"

 

The point is to exploit polymorphism by programming to a supertype so that the actual runtime object isn't locked into the code,And we could rephrase "program to a supertype" as "the declared type of the variables should be a supertype,usually an abstract class or interface",so that the objects assigned to those variables can be of any concrete implementation of the supertype,which means the class declaring them doesn't have to know about the actual object types!"

 

4. Design Principle 3

 

优先使用对象组合吗,而不是类继承

 

使用组合简历系统具有很大的弹性,不仅可将算法族封装成类,更可以“在运行时动态地改变行为”,只要组合的行为对象符合正确的接口标准即可。

 

Favor composition over inheritance 

 

Creating system using composition gives you a lot more flexibility.Not only does it let you encapsulate a family of algorithms into their own set of classes,but it also lets you change behavior at runtime as long as the object you are composing with implements the correct behavior interface.

 

OO设计原则:

 

【单一职责原则】:就一个类而言,应该仅有一个引起它变化的原因

 

【开放封闭原则】:类应该对扩展开发,对修改关闭(关键是抽象,将一个功能的通用部分和实现细节部分清晰的分离开来, 应该仅仅对程序中呈现出频繁变化的那些部分作出抽象)

 

【李氏替换原则】:子类型(subclass)必须能够替换掉它们的基类型(superclass)

 

【依赖倒置原则】:要依赖抽象,不要依赖具体类(抽象不应该依赖于细节,细节应该依赖于抽象,程序中所有的依赖关系都应该终止于抽象类和接口,针对接口而非实现编程)

 

【接口隔离原则】:不应该强迫客户依赖于它们不用的方法

 

【接口设计原则】:IDP(Interface Design Principle),规划一个接口而不是实现一个接口

 

【缺省抽象原则】:DAP(Default Abstraction Principle),在接口和实现接口的类之间引入一个抽象类,这个类实现了接口的大部分操作

 

【黑盒原则】:BBP(Black Box Principle),多用类的聚合,少用类的继承

 

包的内聚性原则: 


1) 重用发布等价原则(The Release Reuse Equivalency Principle (REP)) 
* 重用的粒度就是发布的粒度 
* 一个可重用的包必须为发布跟踪系统所管理,使我们在新版本发布后我们还可以继续使用老版本 
* 一个包中的所有类对于同一类用户来讲都应该是可重用的。 

2) 共同重用原则(The Common Reuse Principle (CRP)) 
* 一个包中的所有类应该是共同重用的,如果重用了包中的一个类,就应该重用包中的所有类。 
* 一般来说,可重用的类需要与作为该可重用抽象一部份的其它类协作,CRP规定了这些类应该属于同一个包。 
* 放入同一包中的所有类应该是不可分开的,其它包仅仅依赖于其中一部份情况是不可能的(不允许的),否则,我们将要进行不必要的重新验证与重新发布,并且会白费相当数量的努力。(一个包依赖于另外一个包, 哪怕只是依赖于其中的一个类也不会削弱其依赖关系) 
* CRP倾向于把包做的尽可能的小 

3) 共同封闭原则(The Common Closure Principle (CCP)) 
* 包中的所有类对于同一类性质的变化应该是共同封闭的。一个变化若对一个包产生影响,则将对该包中所有类产生影响,而对于其他的包不造成任何影响。 
* 这是单一职责原则对于包的重新规定。 
* CCP鼓励我们把可能由于同样的原因而更改的所有类共同聚集在同一个地方。将变化限制在最小数据的包中。 
* CCP倾向于将包做的尽可能的大。 
* CCP有益于维护者(包的作者),而REP和CRP有益于重用者(包的使用者)。 

包的耦合性原则:


1) 无环依赖原则(The Acyclic Dependencies Principle (ADP)) 
* 在包的依赖关系图中不允许存在环。 
* 包的依赖关系图应该是一个有向无环图(DAG(Directed Acyclic Grphic)) 
* 存在环的系统,很难确定包的构建顺序,事实上,并不存在恰当的构建顺序。 
* 打破环的第一个方法:依赖倒置原则,使一个包不再依赖于另一个包,而只是依赖于其抽象接口。 
* 打破环的第二个方法: 创建一个新包来包含公共依赖部份。 

2) 稳定依赖原则(The Stable Dependencies Principle (SDP)) 
* 朝着的稳定的方向进行依赖 
* 你设计了一个易于更改的包, 其它人只要创建一个对它的依赖就可以使它变的难以更改,这就是软件的反常特性。通过遵循SDP可以避免这种情况。 
* 不稳定性度量:I = Ce / (Ca + Ce). Ca: Afferent Coupling. Ce: Efferent Coupling 
* SDP规定一个包的I度量值应该大于它所依赖的包的I的度量值,也就是说,I的度量值应该顺着依赖的方向减少。 

3) 稳定抽象原则(The Stable Abstractions Principle (SAP)) 
* 包的抽象程度应该和其稳定程度一致。 
* 一个稳定的包同时应该是抽象的,这样,其稳定性就不会导致其无法扩展。一个不稳定的包应该是具体的,这样,因为其不稳定性使得其内部的具体代码易于修改。 
* 抽象性度量:A = Na / Nc Na: Number of classes. Nc:Number of abstract classes. 
* 创建一个以A为纵轴,I为横轴的坐标图,最稳定,最抽象的包位于左上角(0,1)处, 那些最不稳定,最具体的包位于右下角(1,0)处。 

 

23种设计模式 - Pattern:

 

创建型:

Abstract Factory(抽象工厂模式) -> (简单工厂模式) 

Factory Method(工厂模式) 

Builder(生成器模式) 

Singleton(单件模式) -> (多例模式) 

Prototype(原型模式)

 

结构型: 

Adapter(适配器模式) 

Bridge(桥接模式) 

Composite(组合模式) 

Decorator(装饰模式) 

Facade(外观模式,门面模式) 

Flyweight(享元模式) -> (不变模式) 

Proxy(代理模式)

 

行为型:

Chain of Responsibility(职责链模式) 

Command(命令模式) 

Interpreter(解释器模式) 

Iteartor(迭代器模式) 

Mediator(中介者模式) 

Memento(备忘录模式) 

Observer(观察者模式) 

State(状态模式) 

Strategy(策略模式) 

TemplateMethod(模板方法模式) 

Visitor(访问者模式) 

 

 

 1.【观察者模式】:定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新;主题(Subject)和观察者(Observer)定义了一对多的关系。

 



 

【松耦合】

 

当两个对象之间松耦合,他们依然可以交互,但是不太清楚彼此的细节。

 

观察者模式提供了一种对象设计,让主题和观察者之间松耦合。

 

主题只知道观察者实现了某个接口(Observer接口),主题不需要知道观察者的具体类是谁、做了些什么或其他任何细节。

 

任何时候我们都可以增加新的观察者。因为主题唯一依赖的东西是一个实现了Observer接口的对象列表,所以我们可以随时增加观察者,也可以在任何时候删除某些观察者。

 

有新类型的观察者出现时,主题的代码不需要修改。新类型的观察者只要实现观察者接口(Observer接口),然后注册为观察者即可。主题不在乎别的,他只会发送通知给所有实现了观察者接口的注册对象。

 

改变主题或观察者其中一方,并不会影响另一方。因为两者是松耦合的,所以只要他们之间的接口仍被遵守,我们就可以自由地改变他们。

 

 观察者模式采用主题【推】的模式,将主题的变动通知所有注册的观察者,而不是采用观察者【拉】的模式。

 

 

2.【装饰模式】:装饰者和被装饰对象有相同的超类型,动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案。不改变接口,但加入责任

 

 

 

 

3.【工厂方法模式】:定义了一个创建对象的接口,但由子类决定要实例化的类时哪一个。工厂方法让类把实例化推迟到子类。

 



 

利用工厂方法创建对象,需要扩展一个类(使用继承),并覆盖他的工厂方法,通过子类来创建对象,由子类来负责决定具体类型。把客户代码从需要实例化的具体类中解耦。

 

 

 4.【抽象工厂模式】:提供一个接口,用于常见相关或依赖对象的家族,而不需要明确指定具体类。

 

抽象工厂允许客户使用抽象的接口来创建一组相关的产品,而不需要知道(或关心)实际产出的具体产品是什么。这样一来,客户就从具体的产品中被解耦。

 


 

 

抽象工厂的方法经常以工厂方法的方式实现。抽象工厂的任务是定义一个负责创建一组产品的接口。这个接口内的每个方法都负责创建一个具体产品。我们利用实现抽象工厂的子类来提供这些具体的做法。所以,在抽象工厂中利用工厂方法实现生产方法是相当自然的做法。

 

 抽象工厂提供一个用来创建一个产品家族的抽象类型,这个类型的子类定义了产品被产生的方法。把客户从所使用的实际具体产品中解耦。

 

 5.【命令模式】:将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。

 

6.【适配器模式】:适配器模式的工作是将一个接口转换成另一个接口,适配器模式将一个类的接口,转换成客户期望的另一个接口。适配器让原来接口不兼容的类可以合作无间。

 

7.【外观模式】:提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。

 

它改变接口的原因是为了简化接口,因为它将一个或数个类的复杂的一切都隐藏在背后,只显露出一个干净美好的为外观。外观模式不只是简化了接口,也将客户从组件的子系统中解耦。

 

8.【模板方法模式】:在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。

 

模板方法定义了一个算法的步骤骨架,它被声明为final,以免子类改变这个算法的顺序。并允许子类为一个或多个步骤提供实现。

 

abstract class AbstractClass{

 

    final void templateMethod(){

      primitiveOperation1();

      primitiveOperation2();

      concreteOperation1();

      concreteOperation2();

    }

 

    abstract void primitiveOperation1();

 

    abstract void primitiveOperation2();

 

    final void concreteOperation1(){

    //这里是实现

    }

 

    final void concreteOperation2(){

    //这里是实现

    }

}

 

 

模板方法模式为我们提供了一种代码复用的重要技巧。

 

 策略模式和模板方法模式的区别:

策略模式和模板方法模式都是封装算法,一个用组合,一个用继承。

 

 外观模式和适配器模式的区别:

外观模式和适配器模式可以包装许多类,两种模式的差异,不在于他们“包装”了几个类,而是在于他们的意图,外观的意图是简化接口,而适配器的意图是将接口转换成不同接口。

 

 适配器模式和装饰器模式的区别:

适配器模式的意义是要将一个接口转变成另外一个接口,他的目的是通过改变接口来达到重复使用的目的;而装饰器模式不是要改变被装饰对象的接口,而是恰恰要保持原有的接口,但是增强原有对象的功能,或者改变原有对象的处理方法而提升性能。

 

 适配器将一个对象包装起来以改变其接口;装饰者将一个对象包装起来以增加新的行为和责任;外观将一群对象“包装”起来以简化其接口。

 

 9.【代理模式】:为另一个对象提供一个替身或占位符以控制对这个对象的访问

使用代理模式创建代表对象,让代表对象控制某对象的访问,被代理的对象可以是远程的对象、创建开销大的对象或需要安全控制的对象。

 

适配器会改变对象适配的接口,而代理则实现相同的接口

 

装饰者模式为对象加上行为,而代理则是控制访问。

 

 10.【单例模式】:确保一个类只有一个实例,并提供一个全局访问点

 

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;

}

 

}

 

或者

 

public class Singleton{

 

private static Singleton uniqueInstance=new Singleton();

 

private Singleton(){}

 

public static Singleton getInstance(){

 

return uniqueInstance;

}

 

}

 

 

 装饰者模式:包装一个对象,以提供新的行为

状态模式:封装了基于状态的行为,并使用委托在行为之间切换

迭代器模式:在对象的集合之中游走,而不暴露集合的实现

外观模式:简化一群类的接口

策略模式:分装可以互换的行为,并使用委托来决定要使用哪一个

代理模式:包装对象,以控制对此对象的访问

工厂方法模式:由子类决定要创建的具体类是哪一个

适配器模式:封装对象,并提供不同的接口

观察者模式:让对象能够在状态改变时被通知

模板方法模式:由子类决定如何实现一个算法中的步骤

组合模式:客户用一致的方式处理对象集合和单个对象

单例模式:确保有且只有一个对象被创建

抽象工厂模式:允许客户创建对象的家族,而无需制定他们的具体类

命令模式:封装请求称为对象

 

 

 

 

 

 

 

 

  • 大小: 160.2 KB
  • 大小: 68.5 KB
  • 大小: 119.2 KB
  • 大小: 68.4 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics