您的位置:首页 > 职场人生

黑马程序员——第十章 设计模式

2015-05-13 14:30 218 查看


------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------

 

1. 工厂模式

(1)简单工厂模式

原来需要我们自己去创建对象,现在不需要我们创建,只需要找工厂要就可以了
         Animal
            |-Dog
            |-Cat
            |-Pig
         AnimalFactory
            publicstatic Animal createAnimal

代码体现

/*
 * 顶层父类Animal,所有Animal都有eat()这个方法
 */
public
abstract class
Animal {
   public
abstract void
eat();
}

/*****************************************************/

/*
 * Cat类继承自Animal父类重写eat()方法
 */
public
class
Cat extends Animal {
 
   @Override
   public
void
eat() {
      System.out.println("猫吃鱼");  

   }
}

/*****************************************************/

/*
 * Dog类继承自Animal父类重写eat()方法
 */
public
class
Dog extends Animal {
 
   @Override
   public
void
eat() {
      System.out.println("狗吃骨头");    

   }
}

/*****************************************************/

/*
 * 工厂类,用于生产各个类的实例化对象
 */
public
class
AnimalFactory {
   public
static
Animal createAnimal(String type) {
 
      if ("dog".equals(type)) {
         return
new
Dog();
      } else
if
("cat".equals(type)) {
         return
new
Cat();
      } else {
         return
null
;
      }
   }
}

/*****************************************************/

/*
 * 测试类
 */
public
class
Test {
   public
static void
main(String[]
args) {
      //获取Dog类的实例,调用eat()方法
      Animal a=AnimalFactory.createAnimal("dog");
      a.eat();
     
      //获取Cat类的实例,调用eat()方法
      a=AnimalFactory.createAnimal("cat");
      a.eat();
   }
}

(2)工厂方法模式

简单工厂模式,若需要添加新动物,比如Pig,需要改动代码
这不符合开闭原则,所以出现了工厂方法模式
           
为每个实体新建一个工厂类,添加新动物,只需新添加一个PigFactory即可
不需改动其他代码,拓展性,维护性更好
            Animal
                |--Dog
                |--Cat
                |--Pig
                ...
            AnimalFactory
                |--DogFactory
                |--CatFactory
                |--PigFactory

...

代码体现

/*
 * 顶层父类Animal,所有Animal都有eat()这个方法
 */
public
abstract class
Animal {
   public
abstract void
eat();
}

/*****************************************************/

/*
 * Cat类继承自Animal父类重写eat()方法
 */
public
class
Cat extends Animal {
13fc0

 
   @Override
   public
void
eat() {
      System.out.println("猫吃鱼");  

   }
}

/*****************************************************/

/*
 * Dog类继承自Animal父类重写eat()方法
 */
public
class
Dog extends Animal {
 
   @Override
   public
void
eat() {
      System.out.println("狗吃骨头");    

   }
}

 

/*****************************************************/

/*
 * 工厂类顶层父类,定义了一个抽象方法creatAnimal
 * 子类需重写此方法
 */
public
abstract class
AnimalFactory {
   public
abstract
Animal creatAnimal();
}

/*****************************************************/

/*
 * Cat工厂类,继承自AnimalFactory父类
 * 重写了creatAnimal方法,返回一个Cat类实例
 */
public
class
CatFactory extends AnimalFactory {
 
   @Override
   public Animal creatAnimal() {
      return
new
Cat();
   }
}

/*****************************************************/

/*
 * Dog工厂类,继承自AnimalFactory父类
 * 重写了creatAnimal方法,返回一个Dog类实例
 */
public
class
DogFactory extends AnimalFactory {
   @Override
   public Animal creatAnimal() {
      return
new
Dog();
   }
}

/*****************************************************/

/*
 * 工厂方法模式测试类
 */
public
class
Test {
   public
static void
main(String[]
args) {
         //实例化Dog工厂
         AnimalFactory af=new DogFactory();
         //获取Dog类实例
         Animal a=af.creatAnimal();
         //调用方法
         a.eat();
        
         //实例化Cat工厂
         af=new CatFactory();
         //获取Cat类实例
         a=af.creatAnimal();
         //调用方法
         a.eat();   
   }
}

2.单例模式

分为懒汉式和饿汉式
 
单一实例模式(唯一实例模式)
在内存中,某一个类只有一个实例存在
 
eg:windows打印服务
   网站访问统计
   线程池
 
思路:
   1.构造方法私有,使外界不能随意创建对象
   2.提供私有的、静态的当前类的实例,并且实例化
   3.对外提供公共的获取方法,返回实例化的当前类的实例变量

(1)饿汉式

类加载就创建对象 
开发时采用这种方式,更方便

 

代码体现

/*
 * 饿汉式——类一加载就创建对象
 */
public
class
Student {
 
   // 把构造方法私有,不让外界随意创建
   private Student() {
 
   }
 
   // 类本身要创建一个对象
   // 由于静态只能访问静态,所以对象加静态
   // 为了不让外界通过类名直接访问成员变量,所以加私有
   private
static
Student s =
new
Student();
 
   // 提供公共的方法让外界使用
   // 为了让外界能够使用类名访问该方法,需要对方法加静态
   public
static
Student getStudent() {
      return
s;
   }
 
   public
void
show() {
      System.out.println("单例模式——饿汉式");
   }
}

/*****************************************************/

/*
 * 测试类
 */
public
class
Test {
   public
static void
main(String[]
args) {
      //获取Student对象的实例
      Student s1=Student.getStudent();
      Student s2=Student.getStudent();
      //返回true,说明指向同一个对象
      System.out.println(s1==s2);
     
      s1.show();
      s2.show();
   }
}

 

(2)懒汉式   

什么时候用,就什么时候创建
面试时采用这种方式
延迟加载,节省内存,但是存在线程安全问题,所以必须加锁 

代码体现

/*
 * 懒汉式——用到的时候才创建
 */
public
class
Teacher {
   //私有化构造方法,防止被实例化
   private Teacher() {
 
   }
 
   private
static
Teacher t =
null
;
 
   // t1 t2 t3 3个线程进来
   // 如果t是null的时候,才创建对象,会出现问题(3个同时创建了对象)
   // 所以这种方式必须加锁synchronized
   public
synchronized static
Teacher getTeacher() {
      if (t ==
null) {
         t =
new
Teacher();
      }
      return
t;
   }
 
   public
void
show() {
      System.out.println("单例模式——懒汉式");
   }
}

/*****************************************************/

/*
 * 测试类
 */
public
class
Test {
   public
static void
main(String[]
args) {
      //获取Teacher对象的实例
      Teacher t1=Teacher.getTeacher();
      Teacher t2=Teacher.getTeacher();
      //返回true,说明指向同一个对象
      System.out.println(t1==t2);
      //调用方法
      t1.show();
      t2.show();
   }
}

3.装饰模式

产生原因:
      最初,手机具备打电话的功能
      按照正常的做法,应该将手机类设计出来,并给出一个打电话的功能。
      随着发展,人的需求在变化,假设现在需要在打电话前听到彩铃,那么通过
继承就可以具备父亲打电话的功能,还可以在新手机上添加彩铃功能
      继续发展,需求又变了,希望在打电话之前可以播放广告
      需求继续改变,想先要有彩铃,接着打电话,最后放广告
      需求还可以继续发生变化,虽然使用继承可以解决这些问题,但是,将来一
旦某个父类发生改变,依赖这个父类的所有子类都会受到影响
     
      由于通过长时间的积累,继承体系会异常庞大,父类的改动会影响子类的功
能,且通过继承得到的功能不好控制
 
      设计模式由此产生,用以代替这种模式
  
   装饰模式:对类原有的功能进行修饰或者扩充
        
         A.被装饰的抽象事物Phone
         B.具体事物PhoneImpl
            实现Phone接口,具体的实现类
         C.装饰类PhoneDecorate
            实现Phone接口,调用实现
           
            privatePhone phone;
 
            publicPhoneDecorate(Phone phone) {
               this.phone = phone;
            }
  
            @Override
            publicvoid call() {
                this.phone.call();// 具体的手机打电话功能
            }
        
当功能需要扩展时
            要有彩铃:
                具有彩铃功能的装饰类
            要有广告:
                具有广告功能的装饰类
            ...
        
     
      Phone(接口)
         |--PhoneImpl(具体实现类)
         |--PhoneDecorate(抽象类)
            |--ColorPhoneDecorate(具体装饰类)
           
            |--GuanggaoPhoneDecorate(具体装饰类)

代码体现

/*
 * 被装饰的事物Phone
 */
public
interface
Phone {
   //电话都具有的功能,打电话
   public
abstract void
call();
}

/*****************************************************/

/*
 * 实现类,实现Phone接口
 */
public
class
PhoneImpl implements Phone {
 
   //重写了打电话这个方法
   @Override
   public
void
call() {
      System.out.println("打电话");
   }
}    

 

/*****************************************************/

/*
 * 装饰类PhoneDecorate,实现Phone接口
 */
public
abstract class
PhoneDecorate
implements
Phone {
      private Phone
phone;
      public PhoneDecorate(Phone
phone){
         this.phone=phone;
      }
      @Override
      public 
void
call() {
         this.phone.call();      

      }    
}

     

/*****************************************************/

/*
 * 具体装饰类,具有彩铃功能的装饰类
 * 继承自基本装饰类PhoneDecorate
 * 重写了打电话call()方法
 */
public
class
ColorPhoneDecorate extends PhoneDecorate {
 
   public ColorPhoneDecorate(Phone
phone) {
      super(phone);
 
   }
 
   @Override
   public
void
call() {
      System.out.println("播放彩铃");
      super.call();
   }
}

/*****************************************************/

/*
 * 具体装饰类,具有播放广告功能的装饰类
 * 继承自基本装饰类PhoneDecorate
 * 重写了打电话call()方法
 */
public
class
GuanggaoPhoneDecorate extends PhoneDecorate {
 
   public GuanggaoPhoneDecorate(Phone
phone) {
      super(phone);
   }
 
   @Override
   public
void
call() {
      super.call();
      System.out.println("播放广告");
   }
}

/*****************************************************/

/*
 * 测试类
 */
public
class
Test {
   public
static void
main(String[]
args) {
         //实例化Phone的子类
         Phone p=new PhoneImpl();
         p.call();
         System.out.println("------------");
        
         //实例化彩铃功能的装饰类对象
         PhoneDecorate pd=new ColorPhoneDecorate(p);
         pd.call();
         System.out.println("------------");
        
         //实例化播放广告功能的装饰类对象
         pd=new GuanggaoPhoneDecorate(p);
         pd.call();
         System.out.println("------------");
        
         //添加新功能,播放彩铃-打电话-放广告
         //不必再新定义一个装饰类,而是采用这种方式实现,简化代码
         pd=new GuanggaoPhoneDecorate(new

ColorPhoneDecorate(p));
         pd.call();
         System.out.println("------------");
   }
}

 

 

  

4.模板模式

抽取共性方法,封闭封装,降低耦合性
     
模板类是抽象类,具体实现由继承了模板的子类决定

代码体现1——打印功能

/*
 * 定义了一个打印的模板类
 */
public
abstract class
PrintTemple {
  
   public
abstract void
printHead();
 
   public
abstract void
printBody();
 
   public
abstract void
printBottom();
 
   public
void
print() {
      printHead();
      printBody();
      printBottom();
   }
}

/*****************************************************/

/*
 * 继承模板的一种实现类
 * 重写了模板中的具体实现方法:printHead、printBody、printBottom
 */
public
class
PrintModel1 extends PrintTemple {
 
   @Override
   public
void
printHead() {
      System.out.println("采用第一种方式打印头");
   }
   @Override
   public
void
printBody() {
      System.out.println("采用第一种方式打印中间");
   }
   @Override
   public
void
printBottom() {
      System.out.println("采用第一种方式打印尾");
   }
}

/*****************************************************/

/*
 * 测试类
 */
public
class
Test {
   public
static void
main(String[]
args) {
      //实例化模板的子类对象
      PrintTemple pm=new PrintModel1();
      //调用打印方法
      pm.print();
   } 
}

代码体现2——计算一个功能的运行时间,以模板模式体现

/*
 * 定义一个模板类用于计算function()执行完毕所需时间
 */
public
abstract class
Template {
   public
long
getTime() throws Exception {
      //获取方法执行前,系统的时间
      long
start = System.currentTimeMillis();
      //方法执行
      function();
      //获取方法执行结束后,系统的时间
      long
end = System.currentTimeMillis();
     
      //返回耗时
      return
end-start;
   }
  
   //具体方法,由子类实现
   public
abstract void
function();
}

/*****************************************************/

/*

 * 继承模板类,要测试的功能为:复制一个mp3文件到当前路径下所需时间

 */

import java.io.FileInputStream;

import java.io.FileOutputStream;

 

public class TemplateIODemo extends Template {

 

   //重写要执行的具体方法

   @Override

   public voidfunction() {

      try{

      FileInputStreamfis = new FileInputStream("D:\\test.mp3");

      FileOutputStreamfos = new FileOutputStream("copy.mp3");

      int by = 0;

      while ((by =fis.read()) != -1) {

         fos.write(by);

      }

      fis.close();

      fos.close();

      }

      catch(Exceptione){

         e.printStackTrace();

      }

   }

}

/*****************************************************/

/*
 * 测试类
 */
public
class
Test {
   public
static void
main(String[]
args) throws Exception {
         //实例化子类对象
         TemplateIODemo tio=new TemplateIODemo();
         //获取执行耗时
         long
time=tio.getTime();
         //打印时间
         System.out.println("复制共耗时间:"+time+"毫秒");
   }
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: