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

------<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 {

 

   @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个线程进来

   // 如果tnull的时候,才创建对象,会出现问题(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();

   }

}

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

/*

 * 继承模板的一种实现类

 * 重写了模板中的具体实现方法:printHeadprintBodyprintBottom

 */

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+"毫秒");

   }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值