Java设计模式之Factory工厂设计模式

首先向大家道个歉,这篇文章出的慢。其实呢,我也费了很大的劲来写的,从礼拜天就开始写了,后来因为小区停电了,没有保存,后面不得不重新写了。嗯,昨天晚上又是写到12点了,今天是公司培训,中午回家吃了泡面又接着写下去。下午非常累吧,中途睡着了,财务培训的检测做的很差,估计要挂了,希望不要找我回来再培训啊。条件比较幸苦吧,不管怎么样,我还是必须坚持下去,嗯,加油!!!

这期的文章是Java设计模式系列之Factory工厂模式,内容相对呢多一些,但是我会尽量把她写详细清楚。

工厂模式呢有三种,简单工厂模式工厂方法模式抽象工厂模式。基本掌握前两种就可以了,第三种要慢慢理解,我也是慢慢体会才弄明白的,呵呵,大家应该比我聪明,更容易理解。

简单工厂模式
简单工厂模式就是根据条件产生对象,比如条件为1产生什么对象,条件为2产生什么对象。。。嗯,我这里没有这么做,为了方便起见就打印了句话。
package org.javaer.pattern.factory;

public class SimpleFactory {
    //这里就用到了singleton单例模式
    private static SimpleFactory factory = new SimpleFactory();
    private SimpleFactory(){}
   
    public static SimpleFactory getInstance(){
        return factory;
    }
   
    public void factory(int type){
        if(type==1){//条件为1,打印KFC鸡翅
            System.out.println(“KFC’s chicken wing”);
        }else if(type==2){//条件为2,打印麦当劳鸡翅
            System.out.println(“Mcdonald’s chicken wing”);
        }else{//其他情况,没有鸡翅
            System.out.println(“no chicken wing”);
        }
    }
   
    public void factory(String type){
        if(“KFC”.equals(type)){
            System.out.println(“KFC’s chicken wing”);
        }else if(“Mcdonald’s”.equals(type)){
            System.out.println(“Mcdonald’s chicken wing”);
        }else{
            System.out.println(“no chicken wing”);
        }
    }
    public static void main(String[] args) {
        SimpleFactory simpleFactory = SimpleFactory.getInstance();
        simpleFactory.factory(1);
        simpleFactory.factory(“Mcdonald’s”);
    }
}

——————————————————————————————-简单工厂模式完

我们就可以在配置文件里配置我们要产生的对象的全名就可以了,比如erp.cfg.properties 文件中这样配置org.javaer.erp.dao.DAO=org.javaer.erp.dao.impl.DAOSupport
调用的时候就传入通过读取配置文件得到的Properties类,根据key得到value。有这个字符串,那就容易啦,就像你有了数据库的驱动类的类路径
就用Class.forName(“classname”).newInstance();得到对象,同理是吧。这样就可以通过配置来得到提高系统的可维护性,后面你要是替换实现了,就只要
该配置文件好啦,比如org.javaer.erp.dao.DAO=org.javaer.erp.dao.impl.DAOImpl,那么系统用到这个的时候就会自动全部换掉,而不用一个一个的更改,
是不是方便多了呢。

工厂方法模式
工厂方法我就不多说了,就是多态嘛,父类或接口引用不同的子类对象。我这里用的例子是快餐店生产快餐,有点尴尬了,我不提倡吃快餐的,又贵又没有营养。不过吃的时候貌似不得以而为之,呵呵,下次坚决不吃。
package org.javaer.pattern.factory;

public class FactoryMethod {

    public static void main(String[] args) {
        Store store = new KFCStore();
        store.makeFood();//KFC卖鸡翅
        Store store1 = new McdonaldStore();
        store1.makeFood();//麦当劳卖汉堡
    }

}

//快餐店卖食物
interface Store{
    public Food makeFood();
}
//KFC卖快餐(kfc鸡翅)
class KFCStore implements Store{
    public Food makeFood(){
        return new Food(“KFC wing”);
    }
}
//Mcdonald卖快餐(Mcdonald汉堡)
class McdonaldStore implements Store{
    public Food makeFood(){
        return new Food(“Mcdonald’s hamburger”);
    }
}
//食物类(鸡翅、汉堡)
class Food{
    String name = null;
    public Food(){}
   
    public Food(String name){
        this.name = name;
    }
}

如果你要开个必胜客快餐店,写个类实现Store接口就好了,业务就扩展了。

//必胜客卖食物(披萨)
class Pizzahut implements Store{
    public Food makeFood(){
        return new Food(“Pizza hut pizza”);
    }
}
用的时候就用Store store = new Pizzahut();store.makeFood();
——————————————————————————————————-工厂方法模式完
抽象工厂模式

抽象工厂呢就是在工厂方法模式上面在包一层,因为你的业务可能还需要根据不同的情况产生不同的工厂。
比如我们要有FoodFactory食物工厂,又要有SoftFactory软件工厂。。。那我们就在上面加一层用来产生工厂。而工厂又去生产产品(工厂方法)
package org.javaer.pattern.factory;
//抽象工厂
public abstract class AbstractFactory {

    public abstract FoodFactory createFoodFactory();
    public abstract SoftFactory createSoftFactory();
//测试main方法,懒得再写一测试类
    public static void main(String[] args) {
       
AbstractFactory abstractFactory = new AbstractFactorySupport();
  //产生一级工厂FoodFactory
  FoodFactory foodFactory = abstractFactory.createFoodFactory();
  foodFactory.makeFood();
  System.out.println(“==============================”);
  //产生二级工厂KFCFactory
  KFCFactory kfcFactory =  foodFactory.createKFCFactory();
  kfcFactory.makeFood();
  //产生二级工厂McdonaldFactory
  McdonaldFactory mcdonaldFactory =  foodFactory.createMcdonaldFactory();
  mcdonaldFactory.makeFood();
 
  System.out.println();
 
  //产生一级工厂SoftFactory
  SoftFactory softFactory = abstractFactory.createSoftFactory();
  softFactory.createSoft();
  System.out.println(“=================================”);
  //产生二级工厂IBMFactory
  IBMFactory ibmFactory =  softFactory.createIBMFactory();
  ibmFactory.createSoft();
  //产生二级工厂SUNFactory
  SUNFactory sunFactory = softFactory.createSUNFactory();
  sunFactory.createSoft();
       
    }
}

//抽象工厂实现类,实现产生工厂的抽象方法
class AbstractFactorySupport extends AbstractFactory{
//长生食物工厂
    @Override
    public FoodFactory createFoodFactory() {
        return new FoodFactory();
    }
//产生软件公司
    @Override
    public SoftFactory createSoftFactory() {
        return new SoftFactory();
    }
   
}
//食物工厂
class FoodFactory {
 public void makeFood(){System.out.println(“food factory make food”);}
 public McdonaldFactory createMcdonaldFactory() {return new McdonaldFactory();}
 public KFCFactory createKFCFactory(){return new KFCFactory();}
}

//KFC工厂继承食物工厂,生产KFC食物

class KFCFactory extends FoodFactory {
 public void makeFood(){
  System.out.println(“we make KFC wing”);
 }
}

//Mcdonald工厂继承食物工厂,生产Mcdonald食物

class McdonaldFactory extends FoodFactory {
 public void makeFood(){
  System.out.println(“we make Mcdonald’s wing”);
 }
}

//软件公司开发软件

class SoftFactory {
 public void createSoft(){System.out.println(“soft factory create software”);}
 public SUNFactory createSUNFactory() {return new SUNFactory();}
 public IBMFactory createIBMFactory(){return new IBMFactory();}
}

//IBM公司继承软件工厂,开发软件(IBM软件)

class IBMFactory extends SoftFactory{
 public void createSoft(){
  System.out.println(“we create IBM software”);
 }
}

//SUN公司继承软件工厂,开发软件(开源软件)

class SUNFactory extends SoftFactory{
 public void createSoft(){
  System.out.println(“we create SUN software”);
 }
}

运行AbstractFactory 的main方法输出:

food factory make food
==============================
we make KFC wing
we make Mcdonald’s wing

soft factory create software
=================================
we create IBM software
we create SUN software
我们要加一个手机工厂就可以这样做
//手机生产商设计手机
class MobileFactory{
    public AppleFactory createAppleFactory(){return new AppleFactory();}
    public MeizuFactory createMeizuFactory(){return new MeizuFactory();}
    public Product designMobile(){System.out.println(“mobile factory design mobile”);}
}
//Apple公司设计手机(iPhone4)
class AppleFactory extends MobileFactory{
    public Product designMobile(){
        return new Product(“Apple iphone4″);
    }
}
//魅族公司设计手机(M9)
class MeizuFactory extends MobileFactory(){
    public Product designMobile(){
        return new Product(“Meizu M9″);
    }
}

而在抽象工厂类就添加
public abstract MobileFactory createMobileFactory();
—————————————————————————-抽象工厂模式完
嗯这个抽象工厂我做的不是很好,也是因为我的业务比较松散有关吧,我这里的工厂都是没有关联的FoodFactory,SoftFactory,MobileFactory
网上有例子,我觉得那个更好些。网址是http://zhidao.baidu.com/question/63058512.html,大家可以去看看。

最后呢给出一个综合的例子,加上之前的singleton单例模式,我们做一个JMS发送消息的demo吧。这里有点难懂了,嗯涉及到了EJB3.0中的知识了,不过不必深究了,知道整个程序的大致思路就可以啦。

class ContextHelper{

//这个类是一个单例模式,主要功能有两个1.loadJBOSSProperties(String filename)读取JBOSS的上下文环境配置2.得到上下文,那么我们就可以通过这个上下文从EJB容器中通过JNDI读取对象了Lookup(String ejb)。
        private static ContextHelper chelper = new ContextHelper();
        private ContextHelper(){};
        public static ContextHelper getInstance(){
            return chelper;
        }
        public Properties loadJBOSSProperties(String filename){
            Properties props = new Properties();
            props.load(new FileInputStream(filename));
            return props;
        }
        public Object lookup(String ejb){
            Context conx = new InitailContext(this.loadJBOSSProperties());
            return conx.lookup(ejb);
        }
    }
      
    //发送消息的接口
    interface MessageSender{
        public void sendMessage(Message message);
    }
    //发送一对一消息的实现
    class QueueMessageSender implements MessageSender{
        public void sendMessage(){
            QueueConnectionFctory qcf = (QueueConnectionFctory)ContextHelper.getInstance().lookup(“ConnectionFactory”);
            QueueConnection qconnection = qcf.getConnection();
            QueueSession qs = qconnection.getSession(false,TopicConnection.AUTO_ACKOWNLEDGE);
            Queue queue = (Queue)ContextHelper.getInstance().lookup(“Queue/myQueue”);

    Message message =(TextMessage) queue .createMessage(“我是一个消息”);
            QueueSender qsender = qs.createSender(queue);
            qsender.send(message);
            qs.close();
            qconnection.close();
        }
    }
    //发送一对多消息的实现
    class TopicMessageSender implements MessageSender{
        public void sendMessage(){
            TopicConnectionFctory tcf = (TopicConnectionFctory)ContextHelper.getInstance().lookup(“ConnectionFactory”);
            TopicConnection tconnection = tcf.getConnection();
            TopicSession ts = tconnection.getSession(false,TopicConnection.AUTO_ACKOWNLEDGE);
            Topic topic = (Topic)ContextHelper.getInstance().lookup(“Topic/myTopic”);
          Message message =(TextMessage) topic.createMessage(“我是一个主题”);

     TopicPublisher tp= ts.createPublisher(topic);
            tp.send(message);
            ts.close();
            tconnection.close();
        }
    }
    //消息发送的工厂类
    class MessageSenderFactory{
        public MessageSender createQueueMessageSender(){
            return new QueueMessageSender();
        }
       
        public MessageSender createTopicMessageSender(){
            return new TopicMessageSender();
        }
       
        public static void main(String[] args) {
            MessageSenderFactory msf = new MessageSenderFactory();
            msf.createQueueMessageSender().sendMessage();//我们就发送消息
            msf.createTopicMessageSender().sendMessage();//我们就发送主题
        }
    }

有朋友说文章不是很容易看懂,特别是抽象工厂模式。嗯,我觉得也是,今天有空就再看看,增加了更多的注释,文章机构画一下。有什么意见可以提,不同意见可以排版,还有不明白的可以交流。Skeype:linmei.dong、MSN:[email protected](文/linmei.dong)转载请注明出处http://mtoou.info/java-factory-gcmoshi/

嗯,java设计模式系列之factory工厂模式就写到这里啦,下期是java设计模式系列之Builder构建模式,敬请持续关注~

Java设计模式之singleton单例设计模式

现在网上到处是单例设计模式,都开玩笑说现在满城尽是singleton,呵呵,我也拿出来了,因为我平时用到最多的就是单例设计模式吧,而且比较简单,可以作为Java设计模式的入门篇吧。

SINGLETON—俺有6个漂亮的老婆,她们的老公都是我,我就是我们家里的老公Sigleton,她们只要说道“老公”,都是指的同一个 人,那就是我(刚才做了个梦啦,哪有这么好的事)

单例模式:单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例单例模式。单例模式只应在有真正的 “单一实例”的需求时才可使用。’‘————————–先引用下“从追MM谈Java的23种设计模式”文章中的说法。

单例设计模式形式有4种,一般人只知道有两种,懒汉式和饿汉式。
懒汉式(只有需要的时候才new出来,这里要用synchronized方法或代码块同步,因为在多线程情况下,不同的人同时进来拿到的引用可能都是null,结果都去new了)
public class LazzSingleton{
private LazzSingleton lazzSingleton = null;
 private LazzSingleton() {}//私有构造期 这个很重要啦,如果共有那么外面就可以随便new了,那么我们写这个单例意义就不大了,我发现公司老员工都写public的了,大家要注意下!

public synchronized LazzSingleton getInstance(){
 if(lazzSingleton==null){
   lazzSingleton = new LazzSingleton ();
return lazzSingleton ;
}
return null;
}

}

用的时候就:LazzSingleton lazzSingleton = LazzSingleton.getInstance();

饿汉式(一来就new,拿的时候直接拿对象)
public class HungerSingleton{
private HungerSingleton hungerSingleton = new HungerSingleton ();
private HungerSingleton() {}//私有构造期
public HungerSingleton getInstance(){
return hungerSingleton ;
}
}

用的时候就:HungerSingleton singleton = HungerSingleton.getInstance();

还有一种和饿汉式差不多(Effective Java这本书中有),因为式静态常量,当然内存中只有一个对象啦。
public class StaticFinalSingleton(){
public static final StaticFinalSingleton singleton= new StaticFinalSingleton();

private StaticFinalSingleton (){};//私有构造期
}

用的时候就:StaticFinalSingleton staticFinalSingleton = StaticFinalSingleton.staticFinalSingleton ;

最后一种我记不起来了,用的不多。(我有个坏习惯,嗯,比喜欢记笔记,而且记性不好,希望大家不要学我)

所以实现单例要点:1.私有化构造器(外部不能new),2.用对象名去引用属性(第三种)或静态方法(第一第二种);

应用场景(单例设计模式一般和工厂设计模式联合起来用,等做factory工厂模式时再一起使用,很简单)
如果你的系统中有要读配置文件,那么读配置文件的类就可以用单例设计模式了。例子:
public class LoadProperties {
 private static LoadProperties loadProperties = new LoadProperties();
 private LoadProperties(){};
 
 public static LoadPropertiesgetInstance(){
  return loadProperties
 }
 /**
  * 根据文件名、模块名,从配置文件中取得菜单名
  * @param model
  * @param fileName
  * @return
  */
 public String[] getMenus(String model,String fileName){
  //….
  return null;
 }
 /**
  * 根据文件名,读取显示风格
  * @param fileName
  * @return
  */
 public String[] getStyle(String fileName){
  //……
  return null;
 }

 }
 /**
  * 根据文件名,用户名,读取用户权限,<p>先判断用户级别,然后读取其权限</p>
  * @param fileName
  * @param user
  */

public String[] getPrivileges(String filename,String username){

    return null;

}

//……
}

接下来我们来做个实验,检验到底是不是singleton单例,单线程下我们一眼就看的出来是,所以我们就在多线程下测试。
package org.javaer.code.pattern;

public class Singleton {
 static LazzSingleton lazzSingleton1, lazzSingleton2;
 static HungerSingleton hungerSingleton1, hungerSingleton2;
 static StaticFinalSingleton staticFinalSingleton1, staticFinalSingleton2;

 public static void main(String[] args) {

  while (1 > 0) {
   new Runnable() {
    public void run() {
     lazzSingleton1 = LazzSingleton.getInstance();
     hungerSingleton1 = HungerSingleton.getInstance();
     staticFinalSingleton1 = StaticFinalSingleton.staticFinalSingleton;
    }
   }.run();

   new Runnable() {
    public void run() {
     lazzSingleton2 = LazzSingleton.getInstance();
     hungerSingleton2 = HungerSingleton.getInstance();
     staticFinalSingleton2 = StaticFinalSingleton.staticFinalSingleton;
    }
   }.run();
   System.out.println(lazzSingleton1 == lazzSingleton2 ? “是单例”
     : “不是单例”);
   System.out.println(hungerSingleton1 == hungerSingleton2 ? “是单例”
     : “不是单例”);
   System.out
     .println(staticFinalSingleton1 == staticFinalSingleton2 ? “是单例”
       : “不是单例”);
  }
 }
}

class LazzSingleton {
 private static LazzSingleton lazzSingleton = null;
 private LazzSingleton() {}
 public synchronized static LazzSingleton getInstance() {
  if (lazzSingleton == null) {
   lazzSingleton = new LazzSingleton();//需要的时候new出来
   return lazzSingleton;
  }
  return null;
 }

}

用的时候就:LazzSingleton lazzSingleton = LazzSingleton.getInstance();

class HungerSingleton {
 private static HungerSingleton hungerSingleton = new HungerSingleton();//先new出来
 private HungerSingleton() {}
 public static HungerSingleton getInstance() {
  return hungerSingleton;
 }
}

用的时候就:HungerSingleton singleton = HungerSingleton.getInstance();

class StaticFinalSingleton {
 public static final StaticFinalSingleton staticFinalSingleton = new StaticFinalSingleton();

private StaticFinalSingleton (){};
}

我们比较的是他们的内存地址,显示的结果一直是”是单例”,说明我们写的代码都是正确的单例设计模式。我这里人品比较好啊,用的Thread 和 Runnable实现多线程测试结果都一样,
我之前做过测试发现只有是Rnnable实现的多线程始终是”是单例”,而用Thread实现的多线程有的情况是,有的情况不是。我不是很清楚,貌似这是Rnnable 和Thread实现多线程有区别吧。
我弄了很久也不是很清楚,得看类的源码了,我们就不用关心啦,感兴趣的盆友就去研究下。

总结下:如果你的系统中需要的对象只有一个(为了节约内存,内存对于程序来说是非常重要的,尤其是嵌入式开发。不要以为你的内存大,用户访问多了,服务器的几十的G的内存也受不了,性能下降),如读取配置信息的类(多了去),不同的模块访问的公共类等等;那么就可以用单例设计模式了。Servlet的设计就是单例的,所有的用户拿到的都是服务器上的一个实例对象。(文/linmei.dong)转载请注明出处http://mtoou.info/java-singleton/