先做个简单的自我介绍,我在国内一家知名的公司从事对日外包工作,目前日语一级,一年编程经验。
一直想写一点东西,就针对初学者,探讨一下我对设计模式的学习过程中的感悟吧。这次要写的是简单工厂模式。
最开始学习设计模式的时候,对抽象类和接口这两个概念很是头疼。抽象类和接口类中,往往什么也不实现,只是定义一下方法。既然什么也不做,为什么还要用它们?在最开始自己写一些程序的时候,几乎是不用抽象类和接口。但随着学习的进一步深入,逐渐体会到了这两个东东的好处。下面就结合生活中的一些常见的事情,来和大家探讨一下简单工厂模式,在此过程中,来说说抽象类和接口的作用。
大家都很希望有自己的一套属于自己的房子,于是大家很努力的工作,终于挣到了能够买起一套房子的钱。当大家去看房子时,房地产开发商会拿出很多户型给大家看,让大家选择自己喜欢的设计户型。那么房地产商是如何设计房子呢?作为一个家,客厅,卧室,厨房,卫生间是必不可少的。不管是什么户型的房子,都必须满足这些条件,否则,开发出来的房子就不符合消费者的要求,就卖不出去。这里的“家”,指我们所居住的房子,具有所有户型房子的共同点。如果不满足这些条件,就不能称之为家。我们可以把这个家当作设计模式里面的抽象类来看待,房地产商告诉户型的设计人员,你们设计的房子,必须在满足这个框框(客厅,卧室,厨房,卫生间)的基础上来设计,在满足家的基础上,不同户型的房子,客厅该多大,厨房该多大,卧室该朝哪面,是你们该考虑的事情。但是,这个“家”可不能理解错了,不能按照自己的想法,在里面随便添东东。比如:如果在“家”的卧室里面规定了有两个窗户,那么按照所有的户型房子都必须符合“家”的范畴的规定,所有的户型房子的卧室就都得有两个窗户。但有些消费者就是不喜欢卧室有两个窗户,就喜欢一个窗户,怎么办?所以不能在“家”这个抽象的概念上,增加具体的东西,这样会限制要求满足它的具体事物的扩展性。
  
  //家.
  public abstract class Home {
      //客厅.
      public abstract void Parlor();
   
      //卧室.
      public abstract void Bedroom();
   
      //厨房.
      public abstract void Kitchen();
   
      //卫生间.
      public abstract void Toilet();
}
     在满足“家”的基础上,不同户型的房子,根据不同的消费者,可以设计不同类型的客厅,卧室,厨房,卫生间等等。比如A型住宅,建造好后有一个简单的装修,B型和C型的住宅不需要装修。
//装修.
public interface Fitment {
//客厅装修.
    public void ParlorFitment();
    
    //卧室装修.
    public void BedroomFitment();
    
    //厨房装修.
    public void KitchenFitment();
    
    //卫生间装修.
    public void ToiletFitment();
}
//A型住宅.
public class HouseA extends Home implements Fitment {
   public void Parlor() {
   System.out.println("This is parlor of House A.");
   };
   
   public void Bedroom() {
   System.out.println("This is bedroom of House A.");
   };
   
   public void Kitchen() {
   System.out.println("This is kitchen of House A.");
   };
   
   public void Toilet() {
   System.out.println("This is toilet of House A.");
   };       public void ParlorFitment() {
       System.out.println("This is fitment of parlor.");
    }
    
    public void BedroomFitment() {
        System.out.println("This is fitment of bedroom.");
    }
    
    public void KitchenFitment() {
        System.out.println("This is fitment of kitchen.");
    }
    
    public void ToiletFitment() {
         System.out.println("This is fitment of toilet.");
    }
}上面的A型住宅也许能够说明这个继承和接口,继承,就是“is-a”的关系,而接口则是“has-a”的关系。正如上面的A型住宅,它是一个“家”,并且有装修。而下面的B型和C型住宅,它们都是“家”,但没有装修,一样不影响居住。//B型住宅.
public class HouseB extends Home {
   public void Parlor() {
   System.out.println("This is parlor of House B.");
   };
   
   public void Bedroom() {
   System.out.println("This is bedroom of House B.");
   };
   
   public void Kitchen() {
   System.out.println("This is kitchen of House B.");
   };
   
   public void Toilet() {
   System.out.println("This is toilet of House B.");
   };
}//C型住宅.
public class HouseC extends Home {
   public void Parlor() {
   System.out.println("This is parlor of House C.");
   };
   
   public void Bedroom() {
   System.out.println("This is bedroom of House C.");
   };
   
   public void Kitchen() {
   System.out.println("This is kitchen of House C.");
   };
   
   public void Toilet() {
   System.out.println("This is toilet of House C.");
   };
}但大家在选房子的时候,一般来说是不关心盖房子的过程的(用的是什么水泥,请的是哪个施工队等等),只关心房子的质量。当大家选择好自己喜欢的户型时,跟房地产商洽谈好有关事宜,最后签订买卖合同,合同写明:XXX购买XXX房地产开发商的House X型住宅一套。房地产商觉得这个户型选择的人很多,于是开始建造该户型的房子。//消费者A.    
public class Buyer {
    public static void main(String[] args) {            //找到房地产商,并告诉他,我要A型的房子。
       Landagent landagent = new Landagent();
        HouseA houseA = (HouseA)landagent.BuildHouse("House A");
    
        //房子盖好后,参观房内的卧室,客厅,厨房,卫生间。
       houseA.Bedroom();
      houseA.Kitchen();
      houseA.Parlor();
      houseA.Toilet();
    
        //察看房子的装修。
      houseA.BedroomFitment();
        houseA.KitchenFitment();
        houseA.ParlorFitment();
        houseA.ToiletFitment();    }
}//消费者B.
public class BuyerB {
    public static void main(String[] args) {
         //找到房地产商,并告诉他,我要B型的房子。
     Landagent landagent = new Landagent(); 
     Home houseB = landagent.BuildHouse("House B");         //房子盖好后,参观房内的卧室,客厅,厨房,卫生间。
     houseB.Bedroom();
     houseB.Kitchen();
     houseB.Parlor();
     houseB.Toilet();
    } 
}//
public class BuyerC {
    public static void main(String[] args) {
         //找到房地产商,并告诉他,我要C型的房子。
     Landagent landagent = new Landagent();  
     Home houseC = landagent.BuildHouse("House C");       //房子盖好后,参观房内的卧室,客厅,厨房,卫生间。
     houseC.Bedroom();
     houseC.Kitchen();
     houseC.Parlor();
     houseC.Toilet();
    } 
}//房地产开发商.
public class Landagent {    //根据消费者的选择,建造不同的房子。
    public Home BuildHouse(String houseKind) {
         if (houseKind.equals("House A")) {
                //建造A型房子。
         return new HouseA(); 
         } else if (houseKind.equals("House B")) {
                //建造B型房子。
         return new HouseB();
       } else if (houseKind.equals("House C")) {
                //建造C型房子。
         return new HouseC();
      } else {
         return null;
       }
    }
}简单工厂模式的特点:
工厂类是整个模式的关键所在。它包含必要的判断逻辑,能够根据外界给定的信息,决定究竟应该创建哪个具体类的对象。用户在使用时可以直接根据工厂类去创建所需的实例,而无需了解这些对象是如何创建以及如何组织的。有利于整个软件体系结构的优化。
但是,简单工厂模式的缺点也正体现在其工厂类上,由于工厂类集中了所有实例的创建逻辑,所以“高内聚”方面做的并不好。另外,当系统中的具体产品类不断增多时,可能会出现要求工厂类也要做相应的修改,扩展性并不很好。

解决方案 »

  1.   

    谢谢楼主分享,不过不知道LZ“在国内一家知名的公司从事对日外包工作”是什么意思
    匆匆看了下,既然你的Home类方法都是abstract的,干嘛不把Home改成接口呢,这样的话,可能会更好点吧
    我改了下,你看看吧~
    <code>
      public interface Home { 
          public void Parlor();        //客厅. 
          public void Bedroom();      //卧室. 
          public void Kitchen();     //厨房.
          public void Toilet();     //卫生间. 
    }
    </code>
    <code>
    //房地产开发商. 
    public class Landagent {  
        public static boolean BuildHouse(Object o) { 
            if (o instanceof Home)) { 
                   //根据o的方法进行实现
                   return true;
            } else{
                 return false;
           }
        } 
    }
    </code>
    <code>
    //消费者A.    
    public interface Buyer { 
           public boolean view(Home home);
    }
    public class BuyerImpl implements Buyer{
           //0-argu default constructor
           public boolean view(Home home,Object o){
           if(o instanceof Home){
                 home=o;
                 //利用反射机制遍历方法
               }else{
                     return false;
                      }
           }
    }   
    public class Test(){
        public static void main(String[] args){
               Buyer buyer=new BuyerImpl();
               Home houseA=new HouseA();
               buyer.view(houseA,new HouseA());
         }

      

  2.   

    //家. 
      public abstract class Home { 
          //客厅. 
          public abstract void Parlor(); 
      
          //卧室. 
          public abstract void Bedroom(); 
      
          //厨房. 
          public abstract void Kitchen(); 
      
          //卫生间. 
          public abstract void Toilet(); 

      

  3.   


    回chenniaoc:
      其实经验很简单,就是持之以恒。
     之所以能这么快就到一级水平,主要就是每天都坚持练习听力,每天都坚持记忆单词和语法。平日在工作的时候多加运用,尽可能的不用翻译。只要能做到持之以恒,就一定回有收获。
      

  4.   


    To luhaixun:
    "在国内一家知名的公司从事对日外包工作”意思是由于外包的性质,很少能在实际工作中去运用设计模式。这些感悟都是在工作至于自己学习和思考的,如有不对的地方,虚心接受指正。“既然你的Home类方法都是abstract的,干嘛不把Home改成接口呢”
    我的理解是接口是一种“has-a”的关系,而抽象类是“is-a”的关系,所有居住的房屋都应该是“家”这个抽象概念的一种。
    如果理解的不正确,请指正,虚心聆听!
      

  5.   

    额,问一下"在国内一家知名的公司从事对日外包工作”是想了解一下LZ的情况,没有别的意思,如有什么误会的地方,虚心接受指正。 
    接口是一种“has-a”的关系,而抽象类是“is-a”的关系,我没有说你理解有什么问题,我的意思是如果把Home定义成interface的话,如果有新的房型,那么你的主程序就不需要修改了,只要添加一个实现Home接口的类就行了 
    如果理解的不正确,请指正,虚心聆听!
      

  6.   


    应该都是"is-a"吧,如果是聚合的话才是"has-a"
      

  7.   

    To luhaixun: 
    “额,问一下"在国内一家知名的公司从事对日外包工作”是想了解一下LZ的情况,没有别的意思,如有什么误会的地方,虚心接受指正。”---没有什么误会,呵呵。“接口是一种“has-a”的关系,而抽象类是“is-a”的关系,我没有说你理解有什么问题,我的意思是如果把Home定义成interface的话,如果有新的房型,那么你的主程序就不需要修改了,只要添加一个实现Home接口的类就行了 ”---仔细看了你的代码。觉得你说的很有道理,向你学习!今后也请多多指正!
      

  8.   

    赞一下..日语一级.花了多久过的?
    我今年也要考二级.大概去年九月还是十月开始学的挺担心挂的..没LZ那么厉害哈...努力ING.
    我们公司也基本做对日的...我新人.没做过东西还..感觉LZ蛮行.学习.
      

  9.   

    To LZ:
         LZ好客气呀,一起学习的说~
      

  10.   


    dingxw92:
    我在一本书上看到过这样的说法“继承,就是“is-a”的关系,而接口则是“has-a”的关系。”
    我再仔细调查一下,之后再和dingxw92探讨。
      

  11.   


    To xujiaxiang:
    其实大家只要能坚持到底,都能做到。