java设计模式有哪几种,Java中常用的设计模式

  java设计模式有哪几种,Java中常用的设计模式

  如何解决写爬虫IP受阻的问题?立即使用。

  本教程运行环境:windows7系统,java8版本8,DELL G3电脑。

  

Num1:单例模式

  基本概念:确保一个类只有一个实例,并提供一个全局访问点来访问它。

  常见书写:

  饿汉式

  公共类Singleton{

  私有静态Singleton Singleton=new Singleton();

  私有Singleton(){

  }

  公共静态Singleton getInstance(){

  返回单例;

  }

  }打电话

  Singleton.getInstance()。方法();懒汉式

  公共类Singleton {

  /*保存私有静态实例以防止其被引用。这里,为了延迟加载,赋值为空*/

  私有静态单例实例=null

  /*私有构造方法以防止它被实例化*/

  私有Singleton() {}

  /* 1:惰性静态工程方法,创建实例*/

  公共静态Singleton getInstance() {

  if (instance==null) {

  instance=new Singleton();

  }

  返回实例;

  }

  受保护的void方法(){

  system . out . println( singleton inner );

  }

  }电话:

  Singleton.getInstance()。方法();优点:延迟加载(只在需要的时候加载),适合单线程操作。

  缺点:线程不安全,多线程中容易不同步,比如频繁的数据库对象读写操作。

  双重线程检查模式

  公共类SingletonInner {

  private static volatile singleton inner sInst=null;//这里添加了volatile

  /**

  *私有构造函数

  */

  private SingletonInner() {}

  公共静态SingletonInner getInstance() {

  if(inst==null){ synchronized(singleton inner . class){ if(inst==null){

  sInst=new singleton inner();

  }

  }

  }返回sInst

  }受保护的void方法(){

  system . out . println( singleton inner );

  }

  }电话:

  Singleton.getInstance()。方法();优点:线程安全,支持延迟加载,调用效率高

  缺点:文笔复杂,不简洁。

  内部类的实现

  公共类SingletonInner {

  /**

  *内部类实现单例模式。

  *延迟加载以减少内存开销。

  */

  私有静态类SingletonHolder {

  private static singleton inner instance=new singleton inner();

  }

  /**

  *私有构造函数

  */

  private SingletonInner() {}

  公共静态SingletonInner getInstance() {

  返回SingletonHolder.instance

  }

  受保护的void方法(){

  system . out . println( singleton inner );

  }

  }电话:

  Singleton.getInstance()。方法();优点:延迟加载,线程安全(java中类加载是互斥的),内存消耗也减少了。建议使用内部类模式。

  

Num2:工厂模式

  基本概念:提供创建对象的过渡接口,从而屏蔽和隔离创建对象的具体过程,达到提高灵活性的目的。

  分为三类:

  工厂法模式简单工厂:不利于生产系列产品;

  工厂模式工厂方法:又称多态工厂;

  抽象工厂抽象工厂:又称工具箱,它生产产品族,但不利于新产品的生产;

  这三种模式自上而下逐渐抽象,更加通用。在《设计模式》一书中,GOF将工厂模式分为两类:工厂方法和抽象工厂。工厂方法模式作为工厂方法模式的特例,两者归为一类。

  简单工厂模式

  工厂方法模式也称为静态工厂方法模式。从重命名可以看出,这个模式一定很简单。它的目的很简单:定义一个创建对象的接口。

  在工厂方法模式中,工厂类处于产品类实例化调用的中心,它决定应该实例化哪个产品类,就像交通警察站在交通流中决定在哪个方向释放交通一样。

  我们来看看它的构成:

  类角色:这是这个模型的核心,包含一定的业务逻辑和判断逻辑。在java中,它通常由一个具体的类来实现。抽象产品角色:一般是具体产品或者实现的接口继承的父类。它是由java中的接口或抽象类实现的。特定产品角色:由工厂类创建的对象是该角色的一个实例。它是由java中的一个具体类实现的。示例代码:

  publicfactory {//getclass生成的样本一般可以使用动态类加载来加载类。

  公共静态样本创建者(int which){

  if (which==1)

  返回新SampleA();

  else if (which==2)

  返回新的SampleB();

  }

  }目前另一个流行的规范是将静态工厂方法命名为valueOf或getInstance。

  值:此方法返回的实例与其参数具有相同的值,例如:

  integer a=integer . value of(100);//返回值为100 {

  私有最终浮动环;

  私有最终浮动im;

  私有组合(浮动re,浮动im){

  this.re=re

  this.im=im

  }

  公共静态复数值Of(float re,float im){

  返回新复合体(re,im);

  }

  公共静态复数值OfPolar(float r,float theta){

  返回新的复数((float)(r * Math.cos(theta)),(float)(r * math . sin(theta));

  }

  }从上面的代码可以看出,valueOf()方法可以执行类型转换操作。在这种情况下,int类型的基本数据被转换为Integer对象。

  GetInstance:返回的实例与参数匹配,例如:

  calendar cal=calendar . getinstance(区域设置。中国);//返回符合中国标准的日历工厂方法模式

  工厂方法模式是工厂方法模式的进一步抽象和推广。在工厂方法模式中,决定应该实例化哪个产品类的不再仅仅是一个工厂类。这个决定交给抽象工厂的子类。

  看看它的构成:

  抽象工厂角色:这是工厂方法模式的核心,与应用无关。是特定工厂角色必须实现的接口或必须继承的父类。在java中,它是由抽象类或接口实现的。特定工厂角色:包含与特定业务逻辑相关的代码。应用程序调用的对象,用于创建相应的具体产品抽象产品角色:它是具体产品或实现的接口继承的父类。一般java里都有抽象类或者接口。特定产品角色:由特定工厂角色创建的对象是该角色的实例。它是由java中的具体类实现的。工厂模式使用从抽象工厂角色继承的多个子类来代替工厂方法模式中的“神类”。如上所述,这样会分担物体上的压力;这使得结构更加灵活。3354当一个新产品(也就是暴发户的车)产生时,只要是根据抽象产品角色和抽象工厂角色提供的契约生成的,就可以被客户使用,不需要修改任何已有的代码。可见工厂角色的结构也是符合开闭原则的!

  示例代码:

  //抽象产品角色

  公共接口可移动{

  空运行();

  }

  //特定的产品角色

  公共类平面实现可移动{

  @覆盖

  公共无效运行(){

  System.out.println(plane . );

  }

  }

  //特定的产品角色

  公共类扫帚工具可移动{

  @覆盖

  公共无效运行(){

  System.out.println(broom . );

  }

  }

  //抽象工厂

  公共抽象类车辆工厂{

  抽象可移动create();

  }

  //特定工厂

  公共级飞机制造厂扩建车辆制造厂{

  公共可移动创建(){

  返回新平面();

  }

  }

  //特定工厂

  公共类扫帚厂扩建车辆厂{

  公共可移动创建(){

  return new Broom();

  }

  }

  //测试类

  公共类测试{

  公共静态void main(String[] args) {

  vehicle factory factory=new broom factory();

  可移动m=factory . create();

  m . run();

  }

  }可以看出,随着工厂方法的加入,对象的数量增加了一倍。产品种类多的时候,就会有大量对应的工厂对象,这不是我们想要的。如果这种情况无法避免,可以考虑使用工厂方法模式和工厂方法模式的结合来减少工厂类的数量:即使用工厂方法模式来实现产品树上的相似物种(通常是树的叶子里的兄弟)。

  简单工厂和工厂方法模式的比较

  工厂模式和工厂方法模式的定义之间的区别是显而易见的。工厂方法模式的核心是一个抽象的工厂类,不像工厂方法模式将核心放在一个真实的类上。工厂方法模式可以允许许多真实的工厂类继承抽象工厂类,这实际上可以成为多个工厂方法模式的合成,从而推广工厂方法模式。

  另一方面,工厂方法模式是工厂方法模型的后代。试想一下,如果我们十分确定一个系统只需要一个真实的工厂类,那么我们不妨将抽象的工厂类合并到真实的工厂类中。结果,我们退化到工厂方法模式。

  抽象工厂模式

  示例代码:

  //抽象工厂类

  公共抽象类AbstractFactory {

  公共抽象车辆create Vehicle();

  公共抽象武器create Weapon();

  公共抽象食品create Food();

  }

  //具体工厂类,其中食物,车辆,武器是抽象类,

  公共类DefaultFactory扩展AbstractFactory{

  @覆盖

  公共食品createFood() {

  返回新苹果();

  }

  @覆盖

  公共车辆创建车辆(){

  还新车();

  }

  @覆盖

  公共武器createWeapon() {

  返回新AK47();

  }

  }

  //测试类

  公共类测试{

  公共静态void main(String[] args) {

  abstract factory f=new default factory();

  vehicle v=f . create vehicle();

  v . run();

  武器w=f . create weapon();

  w . shoot();

  food a=f . create food();

  a . print name();

  }

  }在抽象工厂中,AbstractProduct可能是一个或多个,从而形成一个或多个产品族。当只有一个产品族时,抽象工厂实际上退化为工厂方法模式。

  总结

  工厂方法模式是一个具体的类,它创建其他类的实例。父类是相同的,父类是具体的。

  工厂模式是有一个抽象的父类定义一个公共接口,子类负责生成具体的对象。这样做的目的是将类的实例化延迟到子类。

  抽象工厂提供了一个接口来创建一系列相关或相互依赖的对象,而无需指定它们的特定类。它针对的是多产品的层次结构。工厂方法模式针对的是产品的层次结构。

  

Num3:建造(Builder)模式

  基本概念:是一种对象构造的设计模式。它可以抽象出复杂对象(抽象类别)的构造过程,使得这个抽象过程的不同实现方法可以构造出不同性能(属性)的对象。

  构建器模式是逐步创建一个复杂的对象。它允许用户通过指定复杂对象的类型和内容来构建复杂对象。用户不知道具体的内部构造细节。构建器模型和抽象工厂很像,细微的差别只有通过反复使用才能体会到。

  UML结构图:

  上图是策略模式的结构图,可以让我们更方便的描述:

  构建器:为创建产品对象的每个部分指定抽象接口。

  ConcreteBuilder:实现Builder的接口来构造和组装产品的组件,定义和阐明它创建的表示,并提供搜索产品的接口。

  Director:使用Builder接口构造一个对象。

  产品:表示正在构建的复杂对象。ConcreateBuilder创建产品的内部表示,并定义其装配过程。

  为何使用

  将构建复杂对象的过程与其组件分离。注意:是解耦过程和组件。

  因为一个复杂的物体不仅有很多部件,比如汽车,还有很多零件:车轮、方向盘、发动机、各种小零件等等。有很多部分,但远不止这些。如何将这些零件组装成一辆汽车,也是一个复杂的组装过程(需要良好的组装技术)。构建器模式旨在将零件从装配过程中分离出来。

  如何使用

  首先,假设一个复杂的对象是由多个组件组成的。Builder模式将复杂对象的创建与组件的创建分开,组件分别由Builder类和Director类表示。

  首先,您需要一个接口来定义如何创建复杂对象的各个部分:

  公共接口生成器{

  //创建一个组件A比如创建一个汽车车轮void build parta();

  //创建一个组件B比如创建一个汽车方向盘void build partb();

  //创建汽车发动机的VoidBuildRTC()等组件C;

  //返回最终组装结果(返回最后组装的汽车)

  //这里不进行成品的组装过程,而是转移到下面的Director类。

  //从而实现流程与组件产品getResult()的解耦;

  }用Director构建最终的复杂对象,上面的Builder接口中封装的是如何创建零件(复杂对象是由这些零件组成的),也就是说Director的内容是如何最终将零件组装成成品:

  公共类主管{

  私人建筑商;

  公共董事(建筑商)

  this.builder=builder

  }

  //最后将组件partA partB partC组成一个复杂的对象。

  //下面是将车轮、方向盘、发动机组装成汽车的过程。

  公共void构造(){

  builder . build parta();

  builder . build partb();

  builder . build partc();

  }

  }生成器混凝土生成器的具体实现:

  通过具体的完成界面构建器构建或组装产品的部件;并定义它想要创造什么具体的东西;提供一个可以检索产品的界面。公共类ConcreteBuilder实现生成器{

  Part partA,partB,partC

  public void buildPartA() {

  //下面是如何构建的}

  public void buildPartB() {

  //下面是如何构建的}

  public void buildPartC() {

  //下面是如何构建的}

  公共产品getResult() {

  //返回最终的组装结果}

  }复杂对象:产品产品:

  接口产品{复杂对象}的部件:

  接口部分{}让我们看看如何调用构建器模式:

  concrete builder builder=new concrete builder();

  导演导演=新导演(施工员);

  director . construct();

  product product=builder . get result();Builder模式的应用

  在Java的实际使用中,我们经常会用到‘池’这个概念。当资源提供者不能提供足够的资源,并且这些资源需要被许多用户重复共享时,我们需要使用池。“池”实际上是一块内存。当池中存在一些复杂的资源‘肢体’时(比如某个数据库的连接池,可能有时候会断开一个连接),如果回收这些‘肢体’,内存使用效率会提高,池的性能也会提高。在构建器模式下修改Director类,以诊断“断肢”在哪个部位,然后修复这个部位。

  

Num4:观察者模式

  基本概念:观察者模式定义了一对多的依赖关系,允许多个观察者对象同时监听一个主题对象。当这个subject对象的状态发生变化时,它会通知所有的observer对象,以便它们可以自动更新自己。观察者模式也称为发布/订阅模式。

  UML结构图

  上图是观察者模式的结构图,可以让我们更方便的描述:

  Subject类:它将所有对observer对象的引用保存在一个集合中,每个主题可以有任意数量的观察。抽象主题提供了添加和删除观察对象的接口。

  Observer类:抽象observer,它为所有具体的observer定义了一个接口,并在收到主题通知时进行自我更新。

  具体主体类:具体主题,将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。

  具体观察者类:具体观察者,实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。

  如何使用

  例如:老师有电话号码,学生需要知道老师的电话号码以便于在合适的时候拨打,在这样的组合中,老师就是一个被观察者(主题),学生就是需要知道信息的观察者,当老师的电话号码发生改变时,学生得到通知,并更新相应的电话记录。

  先创建一个科目类:

  /**

  *主题(目标,主题):

  * 目标知道它的观察者。可以有任意多个观察者观察同一个目标。

  * 提供注册和删除观察者对象的接口。

  */公共接口主题{

  public void attach(Observer mObserver);

  public void detach(Observer mObserver);

  公示作废通知();

  }创建观察者类:

  /**

  *观察者(观察者,观察者):

  * 为那些在目标发生改变时需要获得通知的对象定义一个更新接口。

  */公共接口观察者{

  公共void update();

  }创建具体主体类:

  /**

  *混凝土主体(具体目标,老师)

  * 将有关状态存入各具体观察对象。

  * 当他的状态发生改变时,向他的各个观察者发出通知。

  */公共课老师实施科目{

  私弦电话;

  私媒生;

  公办教师(){

  电话="";

  学生=新向量();

  }

  @覆盖

  public void attach(Observer mObserver){

  学生。添加(mob server);

  }

  @覆盖

  公共空的分离(观察者移动服务器){

  学生。移除(mob服务器);

  }

  @覆盖

  公开作废通知(){

  for(int I=0;学生们。size();i ){

  ((观察者)学生. get(我).update();

  }

  }

  公共字符串getPhone() {

  回电话;

  }

  公共电话(字符串电话){

  这个电话=电话

  notice();

  }

  }创建具体观察者类:

  /**

  *混凝土观察者(具体观察者,学生):

  * 维护一个指向具体主体对象的引用。

  * 存储有关状态,这些状态应与目标的状态保持一致。

  * 实现观察者的更新接口以使自身状态与目标的状态保持一致。

  */公共类学生实现观察者{

  私有字符串名称;

  私弦电话;

  私人教师教师

  公共学生(字符串名称,教师t){

  this.name=name

  mTeacher=t;

  }

  公共void show(){

  系统。出去。println( Name: Name \ n教师电话:“电话”);

  }

  @覆盖

  公共空的更新(){

  电话=mteacher。get phone();

  }

  }客户端测试:

  /**

  * 观察者(观察员)模式测试类

  */public class ObserverClient {

  公共静态void main(String[] args) {

  向量学生=新向量();

  老师t=新老师();

  for(int I=0;i10i ){

  学生st=新生(安迪.Chen i,t);

  学生。添加(ST);

  t。附加(ST);

  }

  System.out.println(欢迎安迪。陈博客!\n

  观察者模式\n

   - );

  t。设置电话( 12345678 );

  for(int I=0;i3;我)

  ((学生)学生。获取(我))。show();

  t。设置电话( 87654321 );

  for(int I=0;i3;我)

  ((学生)学生。获取(我))。show();

  }

  }程序运行结果如下:

  欢迎来到安迪。陈博客!观察者模式。

  -名字:安迪。陈0

  老师电话:12345678

  姓名:安迪。陈一

  老师电话:12345678

  姓名:安迪。陈2

  老师电话:12345678

  姓名:安迪。陈0

  老师的电话:87654321

  姓名:安迪。陈1

  老师的电话:87654321

  姓名:安迪。陈2

  教师电话:87654321总结

  观察者模式什么时候适用?

  当一个抽象模型有两个方面,其中一个依赖于另一个。将它们封装在独立的对象中,可以使它们独立地改变和重用。

  当改变一个对象需要同时改变其他对象时,我们不知道需要改变多少个对象。

  当一个对象必须通知其他对象,并且它不能假设其他对象是谁时,换句话说,你不希望这些对象紧密耦合。让耦合的双方依靠抽象,而不是具体。

  

Num5:适配器(Adapter)模式

  基本概念:适配器模式将一个类的接口转换成客户端期望的另一个接口,使原本由于接口不匹配而无法协同工作的两个类能够协同工作。

  适配器模式的用途

  以电器为例。一般笔记本电脑的插头都是三相的,也就是除了正极和负极之外,还有一个接地极。但是有些地方的电源插座只有两极,没有接地极。电源插座与笔记本电脑电源插头不匹配,导致笔记本电脑无法使用。当时一个三相转两相的转换器(适配器)就可以解决这个问题,这也正是这种模式所做的事情。

  适配器模式的结构

  适配器模式有两种不同的形式:类适配器模式和对象适配器模式。

  

类适配器模式:

  从上图可以看出,Adaptee类没有sampleOperation2()方法,但是客户端需要这个方法。为了使客户端能够使用Adaptee类,它提供了一个中间链接,即类适配器,它将Adaptee的API与目标类的API连接起来。它是从AdapterAdaptee继承的,这决定了这个适配器模式是类的:

  目标角色:这是预期的接口。注意:因为这里讨论的是类适配器模式,所以目标不能是类。Source (Adapee)角色:现在您需要调整接口。适配器角色:适配器类是这个模式的核心。适配器将源接口转换成目标接口。显然,这个角色不可能是接口,而是一个具体的类。

对象适配器模式:

  从上图可以看出,Adaptee类没有sampleOperation2()方法,但是客户端需要这个方法。为了使客户端能够使用Adaptee类,有必要提供一个包装类适配器。这个包装器类包装了Adaptee的一个实例,因此这个包装器类可以将Adaptee的API与目标类的API连接起来。与适配器Adaptee存在委托关系,这决定了适配器模式是object。

  示例代码:

  公共接口目标{ /**

  *这是源类Adaptee也具有的方法*/

  public void sampleoperation 1();

  /**

  *这是源类Adapteee没有的方法*/

  public void sampleoperation 2();

  }公共类Adaptee { public void sample operation 1(){ }

  }适配器类:

  公共类适配器{

  私有适配者;

  公共适配器(适配器被适配器){

  this.adaptee=adaptee

  }

  /**

  *源类Adaptee具有方法sampleOperation1。

  *这样适配器类可以直接委托。

  */

  public void sampleOperation1(){

  this . adaptee . sample operation 1();

  }

  /**

  *源类Adaptee没有方法sampleOperation2。

  *所以adapter类需要补充这个方法。

  */

  public void sampleOperation2(){

  //写相关代码

  }

  }类适配器和对象适配器的权衡

  类适配器使用对象继承的方法是静态定义方法;而对象适配器采用的是对象组合的方式,也就是动态组合的方式。对于类适配器,因为适配器直接继承Adaptee,所以适配器不能与Adaptee的子类一起工作,因为继承是静态关系。当适配器继承Adaptee时,不可能处理Adaptee的子类。

  对于对象适配器,一个适配器可以使许多不同的信号源适应同一目标。换句话说,同一个适配器可以使源类及其子类适应目标接口。因为对象适配器采用的是对象组合的关系,只要对象类型正确,是不是子类并不重要。

  对于类适配器adapter,可以重新定义Adaptee的一些行为,相当于子类覆盖了父类的一些实现方法。

  很难为对象适配器重新定义Adaptee的行为。在这种情况下,需要定义Adaptee的子类来实现重定义,然后让适配器组合子类。虽然很难重新定义Adaptee的行为,但添加一些新的行为很方便,而且新添加的行为可以同时应用于所有的源。

  对于类适配器,只引入一个对象,不需要额外的引用来间接获取Adaptee。

  对于对象适配器,需要额外的引用来间接获取Adaptee。

  建议尽量使用对象适配器的实现,多合成或聚合,少继承。当然具体问题具体分析,根据需要选择实施,最适合的才是最好的。

  适配器模式的优点

  复用性更好:系统需要使用已有的类,这类的接口不符合系统的需求。然后通过适配器模式可以更好地重用这些功能。

  扩展性更好:在实现适配器功能时,可以调用自开发的函数,从而自然地扩展了系统的功能。

  适配器模式的缺点

  过度使用适配器会让系统非常凌乱,整体难以把握。比如很明显调用了接口A,但实际上内部接口是适配接口b的实现,如果这种情况发生在一个系统上太多,无异于灾难。因此,如果没有必要,可以不使用适配器直接重新配置系统。

  

Num6:代理模式

  基本概念:为其他对象提供代理,以控制对此对象的访问。也可以说,在起点和终点之间有一个中间层,也就是代理。

  为什么要使用

  授权机制不同级别的用户对同一对象具有不同的访问权限。例如,在论坛系统中,使用代理来控制授权机制。访问论坛的有两种人:注册用户和游客(未注册用户),论坛通过类似ForumProxy的代理来控制这两种用户对论坛的访问权限。

  客户端不能直接操作对象,但它必须与该对象进行交互。

  举两个具体例子:

  如果该对象是一个大图片,并且显示它需要很长时间,那么当该图片包含在文档中时,使用编辑器或浏览器打开该文档。必须快速打开文档,不能等大图处理。这时候你需要做一个图像代理,而不是真实的图片。如果那个对象在互联网上的远程服务器上,可能因为网速的原因,直接操作这个对象会比较慢,那么我们可以先用代理来代替那个对象。一句话,原则就是成本高的对象,只有在使用的时候才会被创造出来。这个原则可以为我们节省大量宝贵的Java内存。所以有人认为Java消耗资源和内存,我觉得这和编程思路有关系。

  如何使用

  以论坛系统为例。访问论坛系统的用户有多种类型:注册普通用户、论坛管理员、系统管理员和游客。只有注册用户可以发言,论坛管理员可以管理自己授权的论坛,系统管理员可以管理所有事务等。这些权限由代理划分和管理。

  与论坛运营相关的主要行为显示在论坛中,如论坛名称、论坛描述获取和修改、帖子发布、删除和编辑等。具有不同级别权限的用户在ForumPermissions中定义:

  用于umPermissions的公共类实现可缓存的{

  /**

  *读取对象的权限。

  */

  public static final int READ=0;

  /**

  *管理整个系统的权限。

  */

  public static final int SYSTEM _ ADMIN=1;

  /**

  *管理特定论坛的权限。

  */

  public static final int FORUM _ ADMIN=2;

  /**

  *管理特定用户的权限。

  */

  public static final int USER _ ADMIN=3;

  /**

  *管理特定组的权限。

  */

  public static final int GROUP _ ADMIN=4;

  /**

  *允许调节线程。

  */

  public static final int MODERATE _ THREADS=5;

  /**

  *创建新线程的权限。

  */

  public static final int CREATE _ THREAD=6;

  /**

  *创建新邮件的权限。

  */

  public static final int CREATE _ MESSAGE=7;

  /**

  *允许审核邮件。

  */

  public static final int MODERATE _ MESSAGES=8;

  public boolean isSystemOrForumAdmin(){

  return(values[论坛管理] values[系统管理]);

  }

  //相关操作代码

  }所以论坛中的各种操作权限都和ForumPermissions定义的用户级别有关。作为接口论坛的实现:ForumProxy链接这个对应。比如修改论坛名称,只有论坛管理员或者系统管理员才能修改。代码如下:

  公开课ForumProxy实现论坛{

  私有ForumPermissions权限;

  私人论坛论坛;

  this.authorization=授权;

  公共论坛代理(论坛论坛,授权授权,ForumPermissions权限){

  this.forum=论坛;

  this.authorization=授权;

  this.permissions=权限;

  }

  .

  public void setName(String name)抛出UnauthorizedException,

  ForumAlreadyExistsException{

  //只有系统或论坛管理员可以修改名称。

  if(permissions . issystemorforumadmin()){

  forum.setName(名称);

  }

  否则{

  抛出新的unauthorized exception();

  }

  }

  .

  }而DbForum才是接口论坛的真正实现。以修改论坛名称为例:

  公共类DbForum实现论坛,可缓存{

  .

  public void setName(String name)引发了ForumAlreadyExistsException {

  .

  this.name=name

  //这里真的将新名字保存到数据库中

  save todb();

  .

  }

  .

  }涉及到论坛名称的修改,其他程序都要先处理ForumProxy,由ForumProxy决定是否有权限做某件事。ForumProxy是名副其实的‘网关’和‘安全代理系统’。

  在平时的应用中,不可避免的会涉及到系统的授权或安全体系。不管你是有意识还是无意识的使用代理,你已经在使用代理了。

  流程图

  

Num7:装饰模式

  基本概念:装饰模式,它动态地给一个对象增加一些额外的责任。在添加功能方面,decorator模式比生成子类更灵活。

  UML结构图

  上图是装饰器模式的结构图,这样我们可以做一个更方便的描述:

  组件是定义对象的接口,可以动态地为这些对象添加职责。

  ConcreteComponent定义了一个特定的对象,也可以给这个对象增加一些职责。

  Decorator是一个装饰性的抽象类,它继承了组件,从外部类扩展了组件类的功能,但是对于组件来说,不需要知道Decorator的存在。ConcreteDecorator是一个具体的装饰对象,它可以向组件添加职责。

  如何使用

  场景:有人装扮自己的形象,穿衣服、裤子、鞋子、帽子等。来包装自己,并需要将所需的功能以正确的顺序连接起来进行控制。我们应该如何设计它来做到这一点?如下,先看代码结构图:

  先创建一个接口类:Component.java

  公共接口组件{

  void show();

  }创建一个具体的 ConcreteComponent 来实现 Component 接口:Person.java

  公共类Person实现组件{

  私有字符串名称;

  公共字符串getName() {

   return name;

   }

   public void setName(String name) {

   this.name = name;

   }

   public Person(String name){

   this.name = name;

   }

   @Override

   public void show() {

   System.out.println("装扮的" + name);

   }

  }创建装饰类 Decorator 实现 Component 接口

  public class Decorator implements Component{

   private Component mComponent;

   public void decoratorObj(Component component){

   mComponent = component;

   }

   @Override

   public void show() {

   if(mComponent != null){

   mComponent.show();

   }

   }

  }分别创建具体的装饰类:Jeans.java , Pelisse.java, Sandal.java ...等等,分别继承 Decorator.java 类

  /** 牛仔裤 */

  public class Jeans extends Decorator {

   @Override

   public void show(){

   System.out.println("穿牛仔裤");

   super.show();

   }

  }客户端测试类

  /**

   * 装饰模式测试客户端

   */

  public class DecoratorClient {

   public static void main(String[] args) {

   System.out.println("Welcome to Andy.Chen Blog!" +"\n"

   +"Decorator Patterns." +"\n");

   Person mPerson = new Person("Andy");

   Sandal mSandal = new Sandal();

   Jeans mJeans = new Jeans();

   TShirt mShirt = new TShirt();

   mShirt.decoratorObj(mPerson);

   mJeans.decoratorObj(mShirt);

   mSandal.decoratorObj(mJeans);

   mSandal.show();

   }

  }测试结果

  Welcome to Andy.Chen Blog!

  Decorator Patterns.

  穿凉鞋

  穿牛仔裤

  穿T-Shirt

  装扮的Andy总结

  Decorator模式有以下的优缺点:

  比静态继承更灵活与对象的静态继承相比,Decorator模式提供了更加灵活的向对象添加职责的方式,可以使用添加和分离的方法,用装饰在运行时刻增加和删除职责。使用继承机制增加职责需要创建一个新的子类,如果需要为原来所有的子类都添加功能的话,每个子类都需要重写,增加系统的复杂度,此外可以为一个特定的Component类提供多个Decorator,这种混合匹配是适用继承很难做到的。

  避免在层次结构高层的类有太多的特征,Decorator模式提供了一种“即用即付”的方法来添加职责,他并不试图在一个复杂的可订制的类中支持所有可预见的特征,相反可以定义一个简单的类,并且用Decorator类给他逐渐的添加功能,从简单的部件组合出复杂的功能。

  Decorator 与它的Component不一样Decorator是一个透明的包装,如果我们从对象标识的观点出发,一个被装饰了的组件与这个组件是有差别的,因此使用装饰时不应该以来对象标识。

  产生许多小对象,采用Decorator模式进行系统设计往往会产生许多看上去类似的小对象,这些对象仅仅在他们相互连接的方式上有所不同。

  相关视频教程推荐:Java视频教程

  以上就是java常用的设计模式有哪些的详细内容,更多请关注我们其它相关文章!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: