设计模式学习笔记(3)

原创 2004年08月30日 14:50:00

9.factory method<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

10.simple factory

11.adapter

12.proxy

 

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

 

9.factory method

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

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

实例:

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

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

简单工厂模式的缺点:

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

工厂方法模式的优点:

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

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

<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />

抽象工厂角色(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 <?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />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):担任这个角色的类是由工厂方法模式所创建的对象的父类,或她们共同拥有的接口。一般由接口或抽象类实现。

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

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

 

简单工厂模式优缺点

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

 

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

  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)为对象提供相同的接口。

?

周志华《机器学习》笔记:第3章 线性模型

本章概括 从最简单但也是最基础的线性模型开始研究。线性模型虽然简单,但却是基础。先研究线性、单属性的线性回归问题,在此基础上研究非线性、多属性的回归和分类问题。 第3章 线性模型 单属性...
  • yzqzoom
  • yzqzoom
  • 2016年07月10日 12:11
  • 3129

【学习笔记javascript设计模式与开发实践----1】

个人吐槽 读了不少的关于js的基础书箱,有必要在js的编码结构和编码效率上有所提高(个人资质很差,所以只代表个人观点。如有说的不对的,还请大神们见谅……),个人一直觉得,不会用设计模式不代表你就不是一...
  • pigpigpig4587
  • pigpigpig4587
  • 2015年09月21日 18:09
  • 2145

《李航:统计学习方法》笔记之感知机

感知机学习旨在求出将训练数据集进行线性划分的分类超平面,为此,导入了基于误分类的损失函数,然后利用梯度下降法对损失函数进行极小化,从而求出感知机模型。感知机模型是神经网络和支持向量机的基础。下面分别从...
  • longzaitianya1989
  • longzaitianya1989
  • 2014年09月24日 10:33
  • 6335

HeadFirst 设计模式学习笔记3--装饰模式 Demo

  • 2010年05月12日 16:02
  • 1KB
  • 下载

【学习笔记javascript设计模式与开发实践(闭包和高阶函数)----3】

第3章 闭包和高阶函数 3.1 闭包 对于javascript程序员来说闭包(closure)是一个难懂又必须征服的概念。闭包的形成与变量的作用域以及变量的生存周期密切相关。(虽然前面写了好多遍了,但...
  • pigpigpig4587
  • pigpigpig4587
  • 2015年10月08日 15:09
  • 1175

黑马程序员 java学习笔记3-IO流之字节流与装饰设计模式

---------------------- android培训、java培训、期待与您交流! ---------------------- 装饰设计模式: 当想要对已有的对象功能进行增强时,可以...
  • oybgood1988
  • oybgood1988
  • 2012年02月17日 15:51
  • 319

大话设计模式学习笔记(3,4,5)----单一职责,开放-封闭,依赖倒转,里氏代换原则

由于第3,4,5章讲的是设计模式里面的几个原则,没有讲具体的设计模式,所以我这里就把这三章放在一起写了。不过虽然篇幅短但是由于是原则,这些可是非常重要的。原则性的东西一只手都能数的过来,但是想要完全搞...
  • q1052196521
  • q1052196521
  • 2017年04月24日 15:58
  • 172

【学习笔记javascript设计模式与开发实践(闭包和高阶函数)----3】

第3章 闭包和高阶函数 3.1 闭包 对于JavaScript程序员来说闭包(closure)是一个难懂又必须征服的概念。闭包的形成与变量的作用域以及变量的生存周期密切相关。(虽然前面写了...
  • sunscheung
  • sunscheung
  • 2016年09月29日 16:04
  • 260

[Cocos2D 2.x iOS学习笔记3] 谈 Cocos2D 设计模式

Cocos2D的设计模式不同于iOS一般应用开发所使用的MVC模式。我们知道,在MVC模式中,模型(Model)和视图(View)是完全分开的,通过ViewControllers来连接两部分。而Coc...
  • songrotek
  • songrotek
  • 2013年05月14日 18:29
  • 1733

HeadFirst 设计模式学习笔记3--装饰模式

1.这个模式可以称为“给爱用继承的人一个全新的设计眼界”的模式。牵扯到第五个设计原则:“类应该对扩展开放,而对修改封闭”。但是要注意,遵循这一标准会带来更多层次上的抽象,增加代码的复杂度,所以并不是所...
  • hsttmht
  • hsttmht
  • 2011年11月08日 23:20
  • 481
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:设计模式学习笔记(3)
举报原因:
原因补充:

(最多只允许输入30个字)