设计模式---工厂模式,我的理解,总结

来源:互联网 发布:js json数组长度 编辑:程序博客网 时间:2024/05/17 07:55

1,首先说,什么是设计模式?设计模式为什么会出现?它的出现是为了解决什么问题?

设计模式,design pattern,是一套被反复使用,多数人知晓的,代码设计经验的总结。
设计模式是为了1,提高代码重用性,2,提高代码可扩展性,3,代码更容易被他人所理解,提高代码可读性,保证代码可靠性。

代码引入设计模式的目的大概是以上3个目的, 如何实现这3个目的呢,方式就是,千方百计的降低代码耦合度来实现,引入设计模式也是为了降低代码耦合度从而实现那3个目的。

什么是耦合?怎么解耦和?

其实耦合就是系统内部各个部分之间关联度太高了,牵一发动全身。解耦和就是降低这各个部分之间的关联,解耦和的原则,其实就是设计模式的6大原则,如何解耦和?很简单,其实就是隔离变化,分离变化,将变化的部分单独隔离出来进行处理,这样就降低了各部分之间的关联度,因为已经将一个大部分拆成了很多小部分,

每一种设计模式的出现,都是为了解决现实开发中不断重复发生的问题而不断积淀产生的,可以说,任何一种设计模式,都完美的解决了一种不断重复出现的问题,或者说,是某一种问题的核心的解决方案,设计模式就想模板,使代码编程工程化,实现工厂中流水线一样的作业。

首先说说使用最广泛,最简单的工厂模式,

什么是工厂模式?从字面意思,似乎想到的是一个factory,进去的是原料,出来的是产品,这就是工厂,设计模式,当然是现实的高度抽取,但是又是来自于现实的情景,通过代码解释似乎更否和程序员的逼格。

工厂模式(Factory Method)

没对比就没有伤害,对比一下使用和没使用工厂模式的区别,然后再对工厂进行优化。

1,没有使用工厂模式的情形

interface Fruit{    // 定义一个水果接口    public void eat() ; // 吃水果}class Apple implements Fruit{    public void eat(){        System.out.println("** 吃苹果。") ;    }};class Orange implements Fruit{    public void eat(){        System.out.println("** 吃橘子。") ;    }};public class InterfaceCaseDemo03{    public static void main(String args[]){        Fruit f = new Apple() ; // 实例化接口        f.eat() ;    }};

分析:

这里没有使用工厂,可以发现,代码并没有语法错误,但是设计的真的是糟糕透了,主方法相当于客户端,原则上来说,客户端的代码越少越好,客户端尽可能不要有大的频繁的改动。
然而子这里,可以发现,直接在主方法中指定了要操作的子类,客户端和子类实例紧紧的耦合在了一起,当我想扩展程序,当想要更换子类的时候,想更换一个Orange实例的时候,就肯定需要修改客户端,就必须得再客户端,把子类实例改为new Orangle();就很不合理。

解决:既然发现是耦合度太高,解决方案当然就是解耦和了,

进一步分析:

可以发现,其实问题就是处在这一句代码中Fruit f = new Apple() ;,就是这里存在变化,可能出现若干的不同类型的子类对象,使用父类对象接收子类实例,那么就可以从这个地方着手,隔离变化。

2,初步使用工厂

interface Fruit{    // 定义一个水果接口    public void eat() ; // 吃水果}class Apple implements Fruit{    public void eat(){        System.out.println("** 吃苹果。") ;    }};class Orange implements Fruit{    public void eat(){        System.out.println("** 吃橘子。") ;    }};class Factory{  // 定义工厂类    public static Fruit getInstance(String className){        Fruit f = null ;        if("apple".equals(className)){  // 判断是否要的是苹果的子类            f = new Apple() ;        }        if("orange".equals(className)){ // 判断是否要的是橘子的子类            f = new Orange() ;        }        return f ;    }};public class InterfaceCaseDemo04{    public static void main(String args[]){        Fruit f = Factory.getInstance("apple") ;    // 实例化接口        f.eat() ;    }};

分析:

这里新增了一个类,factory,实例化不同对象的动作,全部归纳在这个类里面进行处理了,实现了这一变化部分的隔离,耦合度果然大大降低了,但是这里又出现了一个新的问题—-》代码健壮性的问题,当传入的参数,不正确,既不是“apple”又不是“ orangle”,而是其他的字符的时候,就返回了一个null对象,这个null去调用eat()方法,当然是会程序崩溃的,如何保证虽然传入了错误的参数,程序依然不崩溃,还给一个提示呢?这就是代码健壮性。

3,优化工厂:

interface Fruit{    // 定义一个水果接口    public void eat() ; // 吃水果}class Apple implements Fruit{    public void eat(){        System.out.println("** 吃苹果。") ;    }};class Orange implements Fruit{    public void eat(){        System.out.println("** 吃橘子。") ;    }};class Factory{  // 定义工厂类    public static Fruit getInstance(String className){        Fruit f = null ;        if("apple".equals(className)){  // 判断是否要的是苹果的子类            f = new Apple() ;        }        if("orange".equals(className)){ // 判断是否要的是橘子的子类            f = new Orange() ;        }        return f ;    }};public class InterfaceCaseDemo05{    public static void main(String args[]){        Fruit f = Factory.getInstance(args[0]) ;    // 实例化接口        if(f!=null){    // 判断是否取得实例            f.eat() ;        }    }};

这个例子里,就做了健壮性验证了,看起来就好多了,

其实可以换一个例子,来说明这个工厂的进化过程:

1,简易工厂

这里写图片描述

public interface Sender {      public void Send();  } public class MailSender implements Sender {      @Override      public void Send() {          System.out.println("this is mailsender!");      }  } public class SmsSender implements Sender {      @Override      public void Send() {          System.out.println("this is sms sender!");      }  } public class SendFactory {      public Sender produce(String type) {          if ("mail".equals(type)) {              return new MailSender();          } else if ("sms".equals(type)) {              return new SmsSender();          } else {              System.out.println("请输入正确的类型!");              return null;          }      }  }测试:public class FactoryTest {      public static void main(String[] args) {          SendFactory factory = new SendFactory();          Sender sender = factory.produce("sms");          sender.Send();      }  }  

以上代码似乎看起来已经不错了,但是还是可以进行优化的:

2,优化工厂—避免返回null对象问题

分析:

在普通工厂方法模式中,如果传递的字符串出错,则不能正确创建对象,而多个工厂方法模式是提供多个工厂方法,分别创建对象。
这里写图片描述

public interface Sender {      public void Send();  } public class MailSender implements Sender {      @Override      public void Send() {          System.out.println("this is mailsender!");      }  } public class SmsSender implements Sender {      @Override      public void Send() {          System.out.println("this is sms sender!");      }  } public Sender SendFactory(){          return new MailSender();      }      public Sender produceSms(){          return new SmsSender();      }  }  public class FactoryTest {      public static void main(String[] args) {          SendFactory factory = new SendFactory();          Sender sender = factory.produceMail();          sender.Send();      }  }

分析:

这就避免了null对象的问题,但是似乎还是可以继续优化呢

3,继续优化工厂—静态工厂

public interface Sender {      public void Send();  } public class MailSender implements Sender {      @Override      public void Send() {          System.out.println("this is mailsender!");      }  } public class SmsSender implements Sender {      @Override      public void Send() {          System.out.println("this is sms sender!");      }  } public class SendFactory {      public static Sender produceMail(){          return new MailSender();      } public static Sender produceSms(){          return new SmsSender();      }  }public class FactoryTest {      public static void main(String[] args) {              Sender sender = SendFactory.produceMail();          sender.Send();      }  } 

分析:

实现了静态工厂,但是似乎发现,这使用了一个工厂对变化进行隔离,似乎还是不够,变化还是不能够很好的控制,当我想扩展功能,比如,现在有发送邮件,发送短信,再扩展一个发送语音的功能的时候,还是要修改之前的代码,要修改工厂,这并不是一个好的现象,并不是一个好的开发设计,需求是——>>>>,

直接新增,要扩展的部分,1:新增自己的代码,2:而不去深入详细阅读之前已经写好的代码,不用深入看懂每一个变量所代表的意思。直接新增自己的代码进工程,就可以完成代码的开发,完成项目的升级扩展

问题:既然需求又一次出来,那怎么做呢????

解决方案:其实很简单,就是继续隔离变化,新增工厂咯。

4继续优化工厂–抽象工厂

仔细分析

上面的工厂方法模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要拓展程序,必须对工厂类进行修改,这违背了闭包原则,所以,从设计角度考虑,有一定的问题,如何解决?就用到抽象工厂模式,创建多个工厂类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。因为抽象工厂不太好理解,我们先看看图,然后就和代码,就比较容易理解。

这里写图片描述

public interface Sender {  //第一工厂接口    public void Send();  } public class MailSender implements Sender {      @Override      public void Send() {          System.out.println("this is mailsender!");      }  } public class SmsSender implements Sender {      @Override      public void Send() {          System.out.println("this is sms sender!");      }  } public interface Provider {  //第二工厂接口    public Sender produce();  }public class SendMailFactory implements Provider {      @Override      public Sender produce(){          return new MailSender();      }  } public class SendSmsFactory implements Provider{      @Override      public Sender produce() {          return new SmsSender();      }  } 测试:public class Test {      public static void main(String[] args) {          Provider provider = new SendMailFactory();          Sender sender = provider.produce();          sender.Send();      }  }

分析:

这样的工厂,当需要扩展一个新的功能,比如发送语音工鞥呢,则只需做一个实现类,语音类,实现Sender接口,同时做一个工厂类,实现Provider接口,就OK了,无需去改动现成的代码。
这样做,拓展性很好,非常棒的满足了需求!

以上代码,类图,来自网络,下面的博客地址,这里拿来学习使用,总结,尊重知识产权。

参考博客:这个帖子写的非常好,
参考下

0 0
原创粉丝点击