黑马程序员_设计模式总结

  ------- android培训java培训、期待与您交流! ----------

 设计模式总结(已学的,不全)

   设计模式是为了解决某一类问题最行之有效的方法。下面是我看视频学习的设计模式的总结。

 1、单例设计模式

  目的:解决一个类在内存中只存在一个对象。

1)禁止其他程序建立该对象。

2)在本类中自定义一个对象,让其他程序访问。

3)提供一些访问方式,使其他程序访问。

  解决方法:

1)将构造函数私有化。

2)在类中创建一个本类对象

3)提供一个方法可以获取到该对象。

 分为两种具体解决方案:1、饿汉式

class Single{

   private Single(){}

   private static Single s = new Single();

   public static Single getInstance(){

       return s;

   }

}

 饿汉式是类一加载到内存是就创建了本类对象。

 

 2、懒汉式

class Single{

   private Single(){}

   private static Single s = null;

   public static Single getInstance(){

       if(s == null){

         synchronized(Single.class){ //加锁,防止多个程序进入,都创建对象

            if(s == null)

              s = new Single();

         }

      }

      return s;

  }

}

 懒汉式是类加载时只创建本类引用,当需要获取实例对象是再创建,称为对象的延迟加载。懒汉式的缺点是在获取对象时需要加锁,防止多个程序进入,都创建对象。这样会让程序效率变低。所以在实际开发中建议使用饿汉式。

 注意:面试时会考到懒汉式。


 

2、装饰设计模式

当想要对已有的对象进行功能加强时,可以自定义类,将已有的对象传入,基于已有的功能,并提供加强功能,那么这个自定义的类就称为装饰类。

装饰类通常会通过构造方法来接收被修饰的对象,并基于被装饰对象的功能,提供更强的功能。装饰比继承更加灵活,降低了类与类之间的关系。

下面是装饰类的例子:

class MyBufferedReader

{

    //Reader类中的read方法只能单个字符的读取,效率比较低

    private Reader r;

    //将Reader类对象作为被装饰类对象传递给MyBufferedReader的构造方法中

    MyBufferedReader(Reader r)

    {

      this.r = r;

    }

    //基于read方法提供readline方法,是效率增强

    public String myReadLine()throws IOException

    {

       StringBuilder sb = new StringBuilder();

       int ch = 0;

       while((ch = r.read()) != -1)

       {

          if(ch == '\r')

             continue;

          if(ch == '\n')

             return sb.toString();

          else

             sb.append((char)ch);

       }

       if(sb.length() != 0)

       {

          return sb.toString();

       }

       return null;

     }

     public void myClose()throws IOException

     {

       r.close();

     }

 }

 public class MyBufferedReaderTest 

 {

     public static void main(String[] args) 

     {

        MyBufferedReader bufr =null;

        try

        {

           bufr = new MyBufferedReader(new FileReader("buffer.txt"));

           String line = null;

           while((line = bufr.myReadLine())!= null)

           {

              System.out.println(line);

           }

        }

        catch(IOException e)

        {

           throw new RuntimeException("读写异常");

        }

        finally

        {

            try

            {

               if(bufr != null)

                 bufr.myClose();

            }

            catch(IOException e)

            {

               throw new RuntimeException("读写异常");

            }

        }

    }

}

红色字体的代码为装饰设计模式的举例,将Reader类作为被装饰类,将其对象作为参数传递给MyBufferedReader类的构造方法中,在此类中提供功能更强大的读取方法,实现读取一行的功能。


 

3、享元设计模式

先举个例子引出享元设计模式:

Integer  a = 56

Integer  b = 56

System.out.println( a == b);结果为true。这是因为当创建Integer对象时,数值大小在一个byte(即-128~127)范围之间时,把对象存放到data区中,当再次创建另一个相同数值的对象时,不再创建新的对象,而是把引用指向已有的对象。

这种现象就是所说的享元设计模式,即当某些对象的属性相同时,不再重复创建,而是把其缓存起来,只将引用指向其已存在的对象即可。这样的设计模式的好处就是,可以节省内存空间。


 

4、状态模式

我们由一个例子引出状态模式:

class Actor{

  public void act(){}

}

class HappyActor extends Actor{

  public void act(){

    System.out.println("HappyActor");

  }

}

class SadActor extends Actor{

  public void act(){

    System.out.println("SadActor");

  }

}

class Stage{

  private Actor actor = new HappyActor();

  public void change(){

    actor = new SadActor();

  }

  public void performPlay(){

    actor.act();

  }

}

public class Transmogrify {

  public static void main(String[] args) {

    Stage stage = new Stage();

    stage.performPlay();

    stage.change();

    stage.performPlay();

  }

}

当你在进行程序设计的时候,首先最好的选择是组合,尤其是不能十分确定应该使用哪一种方式时。组合不会强制我们的程序设计进入继承的层次结构中。且组合更加灵活,可以动态选择类型,相反,继承要在编译时就知道确切类型。

上面的例子中,Stage类中包含一个Actor引用,首先赋值给HappyActor对象。这是performPlay方法会产生特殊的行为。引用也可以在运行时与另外一个不同的对象重新绑定,当actor被重新赋值为SadActor时,performPlay方法有相应产生其特殊行为。这就是所谓的状态模式,即在运行期间获得动态灵活性。而我们不能在运行时决定继承不同的对象,因为它要求在编译期就完全确定下来。

 

5、策略设计模式

import java.util.*;

class Processor{

  public String name(){

    return getClass().getSimpleName();

  }

  Object process(Object input){

    return input;

  }

}

class Upcase extends Processor{

  String process(Object input){

    //协变返回类型

    return ((String)input).toUpperCase();

  }

}

class Downcase extends Processor{

   String process(Object input){

     return ((String)input).toLowerCase();

   }

}

class Splitter extends Processor{

  String process(Object input){

    return Arrays.toString(((String)input).split(" "));

  }

}

public class Apply {

  public static void process(Processor p,Object s){

    System.out.println("Using Processor " + p.name());

    System.out.println(p.process(s));

  }

  public static String s = "Welcome to Heima,good good study,day day up";

  public static void main(String[] args) {

    process(new Upcase(),s);

    process(new Downcase(),s);

    process(new Splitter(),s);

  }

}

上例中Apply.process()方法可以接受任何类型的Processor,并将其应用到一个Object对象上,然后相应打印结果。像这样,创建一个能够根据所传递的参数对象的不同而具有不同行为的方法,被称为策略设计模式。这种方法包含所要执行的算法中固定不变的部分,而“策略”就是包含变化的部分,即传进去的参数对象,它包含要执行的代码。Processor对象就是一个策略,在main()中可以看到三种不同类型的策略应用到了String类型的s对象上。

 

6、适配器设计模式

我们拿Scanner类举例,通过查API知道,Scanner类的构造器接受的是一个Readable接口。我们想要实现以下功能,创建一个随机产生Double类型的数的RandomDoubles类。

import java.util.*;

public class RandomDoubles {

  private static Random rand = new Random(47);

  public double next(){

    return rand.nextDouble();

  }

  public static void main(String[] args) {

   RandomDoubles rd = new RandomDoubles();

   for (int i = 0; i < 7 ; i++) {

     System.out.println(rd.next());

   }

 }

}

这个程序可以产生一个随机Double数,那么我们如何让他作用于Scanner上呢?这是我们就用到了适配器设计模式,创建一个适配器类,该适配器类实现Readable接口,此时我们生成的是一个既是RandomDoubles又是Readable的新类,可以作为Scanner的参数传递进去。

import java.nio.CharBuffer;

import java.util.*;

public class AdaptedRandomDoubles extends RandomDoubles implements Readable{

  private int count;//计数,产生几个随机数

  public AdaptedRandomDoubles(int count){

    this.count = count;

  }

  //重写Readable接口的read()方法

  public int read(CharBuffer cb){

    if(count-- == 0)

      return -1;

    String result = Double.toString(next())+" ";

    cb.append(result);

    return result.length();

  }

  public static void main(String[] args) {

    Scanner s = new Scanner(new AdaptedRandomDoubles(7));

    while(s.hasNextDouble()){

      System.out.println(s.nextDouble() + " ");

    }

  }

}

所谓的适配器模式就是,当我们无法修改你想要使用的类时,如RandomDoubles类,我们就要用到适配器设计模式,适配器中的代码将接受你所拥有的接口,实现接口中的方法,并产生你所需要的接口,如AdaptedRandomDoubles

 

 

7、工厂方法设计模式

接口可以用来实现多重继承,我们生成遵循某个接口的对象的典型方式就是工厂方法设计模式。这与直接调用构造器不同,我们在工厂对象上调用的是创建方法,而该工厂对象将生成接口的某个实现的对象。理论上,这种方式将完全与接口的实现分离,使得我们可以透明的将某个实现替代另一个实现。

下面的例子展示工厂方法的结构:

interface Service{

  void method1();

  void method2();

}

interface ServiceFactory{

  Service getService();

}

class Implementation1 implements Service{

  public Implementation1() {}

  public void method1(){

    System.out.println("Implementation1 method1");

  }

  public void method2(){

    System.out.println("Implementation1 method2");

  }

}

class Implementation1Factory implements ServiceFactory{

  public Service getService(){

    return new Implementation1();

  }

}

class Implementation2 implements Service{

  public Implementation2() {}

  public void method1(){

    System.out.println("Implementation2 method1");

  }

  public void method2(){

    System.out.println("Implementation2 method2");

  }

}

class Implementation2Factory implements ServiceFactory{

  public Service getService(){

    return new Implementation2();

  }

}

public class Factories {

  public static void serviceConsumer(ServiceFactory fact){

    Service s = fact.getService();

    s.method1();

    s.method2();

  }

  public static void main(String[] args) {

    serviceConsumer(new Implementation1Factory());

 

    serviceConsumer(new Implementation2Factory());

  }

}

 下面我们把上面的例子用匿名内部类来简化。

interface Service{

 void method1();

 void method2();

}

interface ServiceFactory{

  Service getService();

}

class Implementation1 implements Service{

  private Implementation1(){}

  public void method1(){

    System.out.println("Implementation1 method1");

  }

  public void method2(){

    System.out.println("Implementation1 method2");

  }

  public static ServiceFactory factory = 

    new ServiceFactory() {

      public Service getService() {

         return new Implementation1();

      }

    };

}

class Implementation2 implements Service{

   private Implementation2(){}

   public void method1(){

     System.out.println("Implementation2 method1");

   }

   public void method2(){

     System.out.println("Implementation2 method2");

   }

   public static ServiceFactory factory = 

     new ServiceFactory() {

       public Service getService() {

         return new Implementation2();

       }

     };

}

public class Factories {

  public static void serviceConsumer(ServiceFactory fact){

    Service s = fact.getService();

    s.method1();

    s.method2();

  }

  public static void main(String[] args) {

    serviceConsumer(Implementation1.factory);

    serviceConsumer(Implementation2.factory);

  }

}

Implementation1Implementation2的构造方法都是private的,并且我们没有必要创建作为工厂的具名类,用匿名类很合适。我们经常使用单一的工厂对象,所以用static修饰。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值