设计模式学习笔记(3)

类别:编程语言 点击:0 评论:0 推荐:

9.factory method

10.simple factory

11.adapter

12.proxy

 

Sorry! 关于factory这类模式,这里的安排顺序不合理,应该先阅读10.Simple factory、然后是9.factory method,最后是8.abstract factory,这样由浅入深,比较好理解,其实就是从产品开始抽象,然后到工厂抽象,然后再到一组工厂的抽象过程。我想这种模式在企业级的开发应该大有作为!

 

9.factory method

说明:估计前一节的实例大家没有看懂,这里在重讲解一下这种模式,请仔细看例子。

注意:这句话我不太明白“这使得工厂方法模式可以允许系统在不修改具体工厂角色的情况下引进新的产品,使其具有超越简单工厂模式的优越性。”不知道这里指的是抽象工厂类还是实例工厂类,但我认为,不论如何实例工厂类在引进新产品的时候都是要修改的,不知道我理解的对不对?

实例:

设计模式C#描述——工厂方法模式

工厂方法模式是类的创建模式,又叫做虚拟构造子模式或多态性工厂模式。它的用意是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类中。

简单工厂模式的缺点:

由于工厂类集中了所有产品创建逻辑的,如果不能正常工作的话会对系统造成很大的影响。如果增加新产品必须修改工厂角色的源码。

工厂方法模式的优点:

在工厂方法模式中,核心的工厂类不再负责所有的产品的创建,而是将创建的工作交给子类去做。这个核心类成为一个抽象工厂的角色,仅负责给出具体工厂子类必须实现的接口,而不接触哪一个产品类实例化的细节。这使得工厂方法模式可以允许系统在不修改具体工厂角色的情况下引进新的产品,使其具有超越简单工厂模式的优越性。

以下面情况为例讨论该模式的具体实现:

抽象工厂角色(Creator):担任工厂方法模式的核心,规定创建对象的工厂类应该实现的接口。

具体工厂角色(ConcereteCreator):负责具体产品对象的创建,实现Creator规定的接口。

抽象产品角色(Product):工厂方法模式所创建对象的超类型,规定产品应具有的接口。

具体产品角色(ConcreteProduct):实现Product所规定的接口。

示例代码如下:

Creator:

public interface Creator

   {

     Product factory();//工厂方法

    }

 

ConcreteCreator1:

 class ConcreteCreator1:Creator

   {

   public Product factory()//工厂方法

   {

     return new ConcreteProduct1();

   }

  }

 

ConcreteCreator2:

   class ConcreteCreator2:Creator

   {

    public Product factory()//工厂方法

    {

      return new ConcreteProduct2();

    }

   }

 

Product:

public interface Product

   {

  

   }

 

ConcreteProduct1:

class ConcreteProduct1:Product

   {

    public ConcreteProduct1()

   {

       Console.WriteLine ("Creat ConcreteProduct1");

    }

   

   }

 

ConcreteProduct2:

   class ConcreteProduct2:Product

   {

    public ConcreteProduct2()

    {

        Console.WriteLine ("Creat ConcreteProduct2");

    }

 

 }

 

Client:

class Client

  {

   private static Creator creator1,creator2;

   private static Product product1,product2;

   [STAThread]

   static void Main(string[] args)

   {

      creator1=new ConcreteCreator1 ();

      product1=creator1.factory();

      creator2=new ConcreteCreator2 ();

      product2=creator2.factory();

    }

  }

 

10.Simple factory

说明:简单工厂模式在《设计模式》(英文版)书中没有提到,但是很多其它模式设计的书都有提及,不知道是不是因为这个模式比较简单直观。这个模式很好理解,就是定义一个统一接口,然后从这个接口派生若干的类,然后用一个工厂类统一创建这些派生类的实例。这和前面的factory method是不一样的,factory method将实际创建工作推迟到了子类。

这种模式的缺点:由于工厂类集中了所有产品创建逻辑的,如果不能正常工作的话会对系统造成很大的影响。如果增加新产品必须修改工厂角色的源码。

实例:

   下面这个实例是我在网上找到的,写的很清楚,非常易懂。

   其实设计模式也并不是什么高深的理论,个人认为并不是象一些人所说的“没写过10万代码就不要谈设计模式”,只要用心学习与实践是完全能够掌握的。??????

 

   简单工厂模式是类的创建模式,又叫做静态工厂方法模式。就是由一个工厂类根据传入的参量决定创建出哪一种产品类的实例。一般涉及到三种角色(如下图):

 

 工厂类(Factory):担任这个角色的是工厂方法模式的核心,含有与应用紧密相关的商业逻辑。工厂类在客户端的直接调用下创建产品对象,它往往由一个具体的类实现。

抽象产品角色(Product):担任这个角色的类是由工厂方法模式所创建的对象的父类,或她们共同拥有的接口。一般由接口或抽象类实现。

具体产品角色(ProductA、ProductB):工厂方法模式所创建的任何对

象都是这个角色的实例,由具体类实现。

 

简单工厂模式优缺点

??? 模式的核心是工厂类,这个类负责产品的创建,而客户端可以免去产品创建的责任,这实现了责任的分割。但由于工厂类集中了所有产品创建逻辑的,如果不能正常工作的话会对系统造成很大的影响。如果增加新产品必须修改工厂角色的源码。

 

以园丁种植水果为例讨论该模式的具体实现:

  Fruit  水果接口,规定水果具有的一些共同特性

  Apple 苹果类 派生自Fruit接口

  Strawberry 草莓类 派生自Fruit接口

  FruitGardener 园丁类 负责草莓与苹果的创建工作。

  当Client要创建水果(苹果或草莓对象)的时候调用园丁类的factory方法创建:UML图如下:

代码如下:

Fruit.cs

namespace Simple_Factory

{

public interface Fruit

{  

  //生长

  void grow();

  //收获

  void harvest();

  //种植

  void plant();

}

}

Apple.cs

namespace Simple_Factory

{

public class Apple:Fruit

  {

  public Apple()

  {

  }

  #region Fruit 成员

  public void grow()

  {

      Console.WriteLine ("Apple is growing.......");

  }

  public void harvest()

  {

      Console.WriteLine ("Apple is harvesting.......");

  }

   public void plant()

  {

  Console.WriteLine ("Apple is planting.......");

  }

  #endregion

  }

}

Strawberry.cs

namespace Simple_Factory

{

  public class Strawberry:Fruit

  {

  public Strawberry()

  {

  }

 #region Fruit 成员

  public void grow()

 {

   Console.WriteLine ("Strawberry is growing.......");

  }

  public void harvest()

  {

   Console.WriteLine ("Strawberry is harvesting.......");

  }

  public void plant()

  {

    Console.WriteLine ("Strawberry is planting.......");

  }

  #endregion

  }

}

FruitGardener.cs

namespace Simple_Factory

{

  public class FruitGardener

  {

  //静态工厂方法

  public static Fruit factory(string which)

  {

  if(which.Equals ("Apple"))

  {

  return new Apple();

   }

  else if(which.Equals ("Strawberry"))

  {

  return new Strawberry ();

  }

  else

  {

  return null;

  }  

  }

 }

}

Client.cs

using System;

namespace Simple_Factory

{

 class Client

  {

  [STAThread]

  static void Main(string[] args)

  {

  Fruit aFruit=FruitGardener.factory ("Apple");//creat apple

  aFruit.grow ();

  aFruit.harvest ();

  aFruit.plant();

  aFruit=FruitGardener.factory ("Strawberry");//creat strawberry

  aFruit.grow ();

  aFruit.harvest ();

  aFruit.plant();

  }

  }

}

输出如下:

Apple is growing.......

Apple is harvesting.......

Apple is planting.......

Strawberry is growing.......

Strawberry is harvesting.......

Strawberry is planting.......

 

 

11.adapter

说明:包括类的适配器模式和对象的适配器模式两种不同的形式,属于比较好理解的模式,具体看下面的代码吧。

适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。??

类的适配器模式把被适配的类的API转换成为目标类的API。

 

实例:

模式的角色如下:

目标(Target)角色:这就是所期待得到的接口。注意这里讨论的是类的适配器模式,因此目标不可以是类。

源(Adaptee)角色:现有需要适配的接口。

适配器(Adapter)角色:把源接口转换成目标接口。

Target;

public interface Target

{

   void sampleOperation1();

   void sampleOperation2();//源类不包含的方法

}// END INTERFACE DEFINITION Target

Adaptee;

public class Adaptee

{

 public void sampleOperation1()

  {

 

  }

}// END CLASS DEFINITION Adaptee

Adapter;

public class Adapter : Adaptee,Target

{

  public void sampleOperation2()

  {

  }

}// END CLASS DEFINITION Adapter

类的适配器模式的效果:

使用一个具体类把源适配到目标中,这样一来,如果源以及源的子类都使用此类适配,就形不通了。

由于适配器类是源的子类,因此可以在适配器类中置换掉(Override)源的一些方法。

与类的适配器模式相似,对象的适配器模式把被适配的类的API转换成目标类的API,与类的适配器模式不同,对象的适配器模式不是使用继承关系连接到Adaptee类,而是使用委派关系,类图如下所示:

 

Target;

public interface Target

{

   void sampleOperation1();

   void sampleOperation2();

}// END INTERFACE DEFINITION Target

Adaptee;

public class Adaptee

{

  public void sampleOperation1()

  {

  

  }

}// END CLASS DEFINITION Adaptee

Adapter:

public class Adapter : Target

{

  private Adaptee adaptee;

  public void Adapter(Adaptee adaptee)

  {

  this.adaptee=adaptee;

  }

  public void sampleOperation1()

  {

  adaptee.sampleOperation1();

  }

  public void sampleOperation2()

  {

  

  }

}// END CLASS DEFINITION Adapter

对象适配器模式的效果:

一个适配器可以把多种不同的源适配到同一个目标。也就是说,同一个适配器可以把源类和它的子类都适配到目标接口。

与类的适配器相比,要想置换源类的方法就不容易。如果一定要置换源类的方法,就只好先做一个源类的子类,将方法置换掉,再把源类的子类当作真正的源进行适配。

 

 

12.proxy

说明:代理模式是比较好理解的一种模式,网上相关的C#例子并不多,下面的这个VB.NET的例子并不是很难,应该很容易看懂,因此不把它用C#重写了。

当我们需要使用的对象很复杂或者需要很长时间去构造,这时就可以使用代理模式(Proxy)。例如:如果构建一个对象很耗费时间和计算机资源,代理模式(Proxy)允许我们控制这种情况,直到我们需要使用实际的对象。一个代理(Proxy)通常包含和将要使用的对象同样的方法,一旦开始使用这个对象,这些方法将通过代理(Proxy)传递给实际的对象。

 一些可以使用代理模式(Proxy)的情况:

    一个对象,比如一幅很大的图像,需要载入的时间很长。

 一个需要很长时间才可以完成的计算结果,并且需要在它计算过程中显示中间结果

 一个存在于远程计算机上的对象,需要通过网络载入这个远程对象则需要很长时间,特别是在网络传输高峰期。

 一个对象只有有限的访问权限,代理模式(Proxy)可以验证用户的权限

代理模式(Proxy)也可以被用来区别一个对象实例的请求和实际的访问,例如:在程序初始化过程中

可能建立多个对象,但并不都是马上使用,代理模式(Proxy)可以载入需要的真正的对象。

    这是一个需要载入和显示一幅很大的图像的程序,当程序启动时,就必须确定要显示的图像,但是实际的图像只能在完全载入后才可以显示!这时我们就可以使用代理模式(Proxy)

 

   这个代理模式(Proxy)可以延迟实际图像的载入,直到它接收到一个paint请求。在实际图像的载入期间我们可以通过代理模式(Proxy)在实际图像要显示的位置预先载入一个比较小、简单的图形。

实例:

简单说明一下这个程序,首先创建图片代理类,内置的定时器5秒钟之后创建实际图片,在此之前创建代理图片。当用户单击按钮后,将图片代理类中的图片对象传递给真真的图片类。

Public Class ImageProxy

  Private done As Boolean

  Private tm As Timer

  Public Sub New()

  done = False

  '设置timer 延迟5秒

  tm = New Timer( _

  New TimerCallback(AddressOf tCallback), Me, 5000, 0)

  End Sub

  Public Function isReady() As Boolean

  Return done

  End Function

  Public Function getImage() As Image

  Dim img As Imager

  '显示预先的图像,直到实际图像载入完成

  If isReady Then

     img = New FinalImage()

  Else

     img = New QuickImage()

  End If

      Return img.getImage

  End Function

  Public Sub tCallback(ByVal obj As Object)

       done = True

  tm.Dispose()

  End Sub

End Class

定义一个简单的接口:

Public Interface Imager

Function getImage() As image

End Interface

实现接口:

预先载入的图像的类:

Public Class QuickImage

  Implements Imager

  Public Function getImage() As Image _

  Implements Imager.getImage

  Return New bitmap("Box.gif")

  End Function

End Class

载入实际图像的类:

Public Class FinalImage

  Implements Imager

  Public Function getImage() As Image _

  Implements Imager.getImage

  Return New Bitmap("flowrtree.jpg")

  End Function

End Class

在显示图像的窗体中,定义一个图像代理的(Proxy)实例,在载入图像按钮事件中,载入图像:    Private imgProxy As ImageProxy

  Public Sub New()

     MyBase.New

     Form1 = Me

     InitializeComponent

     imgproxy = New ImageProxy()

  End Sub

  Protected Sub btLoad_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btLoad.Click

  pic.Image = imgProxy.getImage

  End Sub

总结:

这只是一个很简单的例子(例子来自于《c#设计模式》),通过这个例子可以对代理(Proxy)有初步的认识!Adapter模式代理模式(Proxy)都是在对象间构造一个简单的层。然而,Adapter模式向对象提供一个不同的接口,代理模式(Proxy)为对象提供相同的接口。

?

本文地址:http://com.8s8s.com/it/it28022.htm