单态模式(Singleton)简单工厂(Simple Factory)

第一招:单态模式(Singleton)
如果希望在系统运行的过程中,一个类始终只存在一个实例时,就可以用单态模式。比如对一个程序而言,当前的显示屏、CPU、剪切板始终只有一个,应该用单态模式    来描述这些类。

在一个类中应用单态模式有以下两种常见的方式,称之为“懒汉式”和“饿汉式”。

懒汉式的Singleton饿汉式的Singleton
public  class  Test  {
        private  Test()  {  }

        private  static  Test  instance  =  new  Test();

        public  static  Test  getInstance()  {
                return  instance;
        }
}public  class  Test  {
        private  Test()  {  }

        private  static  Test  instance  =  null;

        public  synchronized  static  Test  getInstance()  {
                if  (instance  ==  null)  {
                        instance  =  new  Test();
                }
                return  instance;
        }
}

按照下面三个步骤就可以实现一个标准的Singleton:
①.将构造函数声明成私有(从语法上防止其他类实例化)
②.声明一个私有静态的自身对象
③.声明一个共有静态的方法,返回自身对象

上面的两端代码在2,3步略有不同,饿汉式可以确保当用户调用getInstance方法后才实例化自身对象,如果实例化的代价很昂贵的话,那么饿汉式可以避免无必要的实例化。但是在多用户的系统中可能会重复实例化,所以方法声明成了synchoronized,会影响一些效率。

单态模式在Java类库中的应用是java.lang.Runtime这个类。还有两个类很像,但不是单态模式:java.lang.Math和java.awt.Toolkit,原因是前者没有返回唯一的自身对象,后者返回的是子类对象。
第二招:简单工厂(Simple  Factory)
简单工厂一般用来返回不同的子类对象。

举个例子,我想开一家店,卖各种电脑配件,包括CPU,显示器,内存,硬盘等,产品结构图如下:

  
图:产品结构

很容易看出,CPU是一个抽象类,有Intel的CPU和AMD的CPU两个子类,显示器则分为了电子管显示器和液晶显示器。好了,现在如果有顾客要来买CPU,该怎么处理呢?你不能直接给顾客一个CPU,因为CPU是抽象类,没有对象,必须要问“您需要什么样的CPU  ?”,如果顾客答“我要Intel的”,就可以实例化一个IntelCPU对象给顾客了。

这个过程看上去理所当然,但是隐藏了一个问题,顾客必须清楚地知道存在IntelCPU这个子类,并了解它的特点,然而并非每个顾客都对自己要买的产品了如指掌。记得若干年前,我和大学同学准备去肯德基开开洋荤,第一次来这种“高档”的餐厅难免令人有些紧张,好不容易排到柜台前,我谨慎的对服务员说:“要两个汉堡”,服务员立刻问道:“请问要哪种汉堡?”,我立刻精神崩溃,啥,汉堡还分好几种?!我只得小声问道:“都有哪几种?”,服务员飞快的报出“香辣鸡腿堡、劲脆鸡腿堡、田园脆鸡堡……”,可怜的我因为紧张一个都没有记住,只能更小声的说“随便吧”……

无论我的第一次肯德基经历会不会引起你的共鸣,都应该从这个例子中看出,强迫使用者记住每一个子类的名称和特性是不合适的,并且子类总是容易的变化的,比如现在CPU流行Intel、AMD,也许十年以后就流行龙芯、威盛,这时使用者的记忆就失去了价值,必须重新熟悉新的产品,可以使用简单类工厂来解决这个问题:

  
图:使用简单类工厂


SimpleFactory.java
public  class  SimpleFactory  {
    
    public  static  final  int  便宜  =  0;
    public  static  final  int  贵  =  1;
    public  static  final  int  随便  =  2;
    
    public  static  CPU  getCPU(int  s)  throws  NoSuchThingException{
        switch  (s)  {
            case  便宜:
                return  new  AmdCPU();
            case  贵:
                return  new  IntelCPU();
            case  随便:
                return  new  IntelCPU();
            default:
                throw  new  NoSuchThingException();
        }
    }
    
    public  static  Display  getDisplay(int  s)  throws  NoSuchThingException{
        switch  (s)  {
            case  便宜:
                return  new  CRT();
            case  贵:
                return  new  LCD();
            case  随便:
                return  new  LCD();
            default:
                throw  new  NoSuchThingException();
        }
    }

}

有了这个SimpleFactory,当我们想得到一个CPU的子类实例时,就不需要记住子类的名称,只要传入常量  “便宜”或者“贵”就好(甚至还可以传“随便”),SimpleFactory会为我们实例化相应的子类对象。而且,即使子类发生了变化,比如以后龙芯取代了Intel,只需要改变SimpleFactory就可以了。

总之,一个简单工厂可以帮助我们实例化各种子类对象,使用简单工厂我们就不需要熟悉子类的具体结构,只需要了解父类就可以了,而且当子类产生变化时(增加或减少子类),我们的程序不会受到影响。

注意:使用SimpleFactory获取对象时,应该用CPU  c  =  SimpleFactory.getCPU(贵)这样的语句,而不是IntelCPU  c  =  SimpleFactory.getCPU(贵),否则就丧失了简单工厂的意义。由此还可以推出,在子类中不应当添加父类中没有定义的公有方法。

一个简单工厂一般有如下几个特征:
①.存在一个或多个产品簇(如本例的CPU产品簇,Display产品簇)
②.创建子类的方法其返回类型为父类类型(如getCPU方法返回CPU类型)
③.创建子类的方法一般需要传入一个标识(如getCPU方法传入一个整型)

简单工厂在Java类库中被大量使用,比如swing中的控件可以添加边框(Border),各种不用的边框子类实例可以通过简单工厂BorderFactory中的方法来得到。

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值