设计模式

单态与工厂模式解析

1. 单态模式

单态模式限制了类实例的创建,但采用这种模式设计的类,可以保证仅有一个实例,并可提供访问该实例的全局访问点。J2EE应用的大量组件,都需要保证一个类只有一个实例。比如数据库引擎访问点只能有一个。

更多的时候,为了提高性能,程序应尽量减少Java对象的创建和销毁时的开销。使用单态模式可避免Java类被多次实例化,让相同类的全部实例共享同一内存区。

为了防止单态模式的类被多次实例化,应将类的构造器设成私有,这样就保证了只能通过静态方法获得类实例。而该静态方法则保证每次返回的实例都是同一个,这就需将该类的实例设置成类属性,由于该属性需要被静态方法访问,因此该属性应设成静态属性。

下面给出单态模式的示例代码:

package  janier.servlet;

  public class SingletonTest {
  private String value;
  private static SingletonTest instance;
  private SingletonTest() {
    System.out.println( "正在执行构造器..." );
    }
   
   public static SingletonTest getInstance() {
   if (instance == null ) {
     instance = new SingletonTest();
   }
   return instance;
   }
  
   public String getValue() {
     return value;
   }
  
   public void setValue(String value) {
     this .value = value;
   }
  
   public static void main(String[] args) {
     SingletonTest t1 = SingletonTest.getInstance();
     SingletonTest t2 = SingletonTest.getInstance();
     t2.setValue( "test" );
     System.out.println(t1 == t2);
    }
 }
 

运行实例,两个打印结果完全相同。这证明单态模式的类全部实例共享一个实例。对于单态模式的类,无论有多少次的创建实例请求,都只执行一次构造器。


2. 工厂模式

工厂模式是专门负责将大量有共同接口的类实例化,而不必事先知道每次是要实例化哪一个类的模式.

工厂模式有几种形态:

简单工厂(Simple Factory)模式,又称静态工厂模式(Static Factory Method Pattern); 工厂方法(Factory Method)模式,又称多态工厂(Polymorphic Factory)模式或虚拟构造子(Virtual Constructor)模式;
抽象工厂(Abstract Factory)模式,又称工具箱(Kit或Tookit)模式。

1). 简单工厂模式

比如说,你有一个描述你的后花园的系统,在你的后花园里有各种的花,但还没有水果。你现在要往你的系统里引进一些新的类,用来描述下列的水果:

葡萄 Grapes 草莓Strawberry 苹果Apple

花和水果最大的不同,就是水果最终是可以采摘食用的。那么,很自然的作法就是建立一个各种水果都适用的接口,这样一来这些水果类作为相似的数据类型就可以和你的系统的其余部分,如各种的花有所不同,易于区分。

 

接口FruitIF的源代码。这个接口确定了水果类必备的方法:种植plant(). 生长grow(),以及收获harvest()。

java 代码
package com.test.simplefactory; public interface FruitIF { void grow(); void harvest(); void plant(); String color = null ; String name = null ; }

类Apple的源代友。苹果是多年生木本植物,因此具备树龄treeAge性质。

java 代码

package com.test.simplefactory; public class Apple implements FruitIF { public void grow() { log("Apple is growing..." ); } public void harvest() { log("Apple has heen harvested." ); } public void plant() { log("Apple has been planted." ); } public static void log(String msg) { System.out.println(msg); } public int getTreeAge() { return treeAge; } public void setTreeAge( int treeAge) { this .treeAge = treeAge; } private int treeAge; }

类Grape的源代码。葡萄分为有籽与无籽两种,因此具有seedful性质。

java 代码

package com.test.simplefactory; public class Grape implements FruitIF { public void grow() { log("Grape is growing..." ); } public void harvest() { log("Grape has heen harvested." ); } public void plant() { log("Grape has been planted." ); } public static void log(String msg) { System.out.println(msg); } public boolean getSeedful() { return seedful; } public void setSeedful( boolean seedful) { this .seedful = seedful; } private boolean seedful; }

类Strawberry的源代码。

java 代码

package com.test.simplefactory; public class Strawberry implements FruitIF { public void grow() { log("Strawberry is growing..." ); } public void harvest() { log("Strawberry has heen harvested." ); } public void plant() { log("Strawberry has been planted." ); } public static void log(String msg) { System.out.println(msg); } }

你作为小花果园的主人兼园丁,也是系统的一部分,自然要由一个合适的类来代表,这个类就是FruitGardener类。这个类的结构请见下面的UML类图。


FruitGardener类会根据要求,创立出不同的水果类,比如苹果APPle,葡萄Grape或草莓Strawberry的实例。而如果接到不合法的要求,FruitGardener类会给出例外BadFruitException。

FruitGardener类的源代码

java 代码

package com.test.simplefactory; public class FruitGardener { public FruitIF factory(String which) throws BadFruitException { if (which.equalsIgnoreCase( "apple" )) { return new Apple(); } else if (which.equalsIgnoreCase( "strawberry" )) { return new Strawberry(); } else if (which.equalsIgnoreCase( "grape" )) { return new Grape(); } else { throw new BadFruitException( "Bad Fruit request" ); } } }

BadFruitException类的源代码

java 代码

package com.test.simplefactory; public class BadFruitException extends Exception { public BadFruitException(String msg) { super (msg); } }

在使用时,只须呼叫FruitGardener的factory()方法即可

java 代码

try { FruitGardener gardener = new FruitGardener(); gardener.factory("grape" ); gardener.factory("apple" ); gardener.factory("strawberry" ); ...}catch (BadFruitException e) { ... }

就这样你的小果园一定会有百果丰收啦!

简单工厂模式的定义 由一个工厂类根据参数来决定创立出那一种产品类的实例。下面的UML类图就精确定义了简单工厂模式的结构。

从上图可以看出, 客户只要面对Factory,客户依赖于产品介面,产品的具体实作是可以与客户隔开的,它们也是可以抽换的。

2). 工厂方法(Factory Method)模式

遇到下面情况时,使用工厂方法:

当一个类不知道它所必须创建的对象的类的时候 当一个类希望由它的子类来指定它所创建的对象的时候 当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信 息局部化的时候

工厂方法(FactoryMethod)模式是类的创建模式,其用意是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类中。

工厂方法模式是简单工厂模式的进一步抽象和推广。由于使用了多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点。

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

在Factory Method模式中,工厂类与产品类往往具有平行的等级结构,它们之间一一对应。

2.1>. 工厂方法模式角色与结构

抽象工厂(Creator)角色: 是工厂方法模式的核心,与应用程序无关。任何在模式中创建的对象的工厂类必须实现这个接口。
具体工厂(Concrete Creator)角色: 这是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建产品对象。在上图中有两个这样的角色:BulbCreator与TubeCreator。
抽象产品(Product)角色: 工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。在上图中,这个角色是Light。
具体产品(Concrete Product)角色: 这个角色实现了抽象产品角色所定义的接口。某具体产品有专门的具体工厂创建,它们之间往往一一对应。

工厂方法的活动序列图


活动过程包括:
客户端创建BulbCreator对象,客户端持有此对象的类型是Creator,而实际类型是BulbCreator。然后客户端调用 BulbCreator的factory方法,之后BulbCreator调用BulbLight的构造函数创造出产品BulbLight对象。

2.2>. 一个简单的实例

java 代码

// 产品 Plant接口 public interface Plant { } //具体产品PlantA,PlantB public class PlantA implements Plant {  public PlantA () {   System.out.println("create PlantA !" );  }  public void doSomething() {   System.out.println(" PlantA do something ..." );  } } public class PlantB implements Plant {  public PlantB () {   System.out.println("create PlantB !" );  }  public void doSomething() {   System.out.println(" PlantB do something ..." );  } } // 产品 Fruit接口 public interface Fruit { } //具体产品FruitA,FruitB public class FruitA implements Fruit {  public FruitA() {   System.out.println("create FruitA !" );  }  public void doSomething() {   System.out.println(" FruitA do something ..." );  } } public class FruitB implements Fruit {  public FruitB() {   System.out.println("create FruitB !" );  }  public void doSomething() {   System.out.println(" FruitB do something ..." );  } } // 抽象工厂方法 public interface AbstractFactory {  public Plant createPlant();  public Fruit createFruit() ; } //具体工厂方法 public class FactoryA implements AbstractFactory {  public Plant createPlant() {   return new PlantA();  }  public Fruit createFruit() {   return new FruitA();  } } public class FactoryB implements AbstractFactory {  public Plant createPlant() {   return new PlantB();  }  public Fruit createFruit() {   return new FruitB();  } }


2.3>. 工厂方法模式与简单工厂模式

工厂方法模式与简单工厂模式再结构上的不同不是很明显。工厂方法类的核心是一个抽象工厂类,而简单工厂模式把核心放在一个具体类上。

工厂方法模式之所以有一个别名叫多态性工厂模式是因为具体工厂类都有共同的接口,或者有共同的抽象父类。

当系统扩展需要添加新的产品对象时,仅仅需要添加一个具体对象以及一个具体工厂对象,原有工厂对象不需要进行任何修改,也不需要修改客户端,很好的符合了"开放-封闭"原则。而简单工厂模式在添加新产品对象后不得不修改工厂方法,扩展性不好。

工厂方法模式退化后可以演变成简单工厂模式。

2.4>. 工厂方法模式演化

使用接口或抽象类
抽象工厂角色和抽象场频角色都可以选择由接口或抽象类实现。

使用多个工厂方法
抽象工厂角色可以规定出多于一个的工厂方法,从而使具体工厂角色实现这些不同的工厂方法,这些方法可以提供不同的商业逻辑,以满足提供不同的产品对象的任务。

产品的循环使用
工厂方法总是调用产品类的构造函数以创建一个新的产品实例,然后将这个实例提供给客户端。而在实际情形中,工厂方法所做的事情可以相当复杂。

一个常见的复杂逻辑就是循环使用产品对象。工厂对象将已经创建过的产品登记到一个聚集中,然后根据客户所请求的产品状态,向聚集查询。如果有满足要求的产品对象,就直接将产品返回客户端;如果聚集中没有这样的产品对象,那么就创建一个新的满足要求的产品对象,然后将这个对象登记到聚集中,再返还给客户端。"享元模式(Flyweight Pattern)"就是这样一个模式。


多态性的丧失和模式的退化
一个工厂方法模式的实现依赖于工厂角色和产品角色的多态性。在有些情况下,这个模式可以出现退化。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值