设计模式---工厂模式,我的理解,总结
来源:互联网 发布: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了,无需去改动现成的代码。
这样做,拓展性很好,非常棒的满足了需求!
以上代码,类图,来自网络,下面的博客地址,这里拿来学习使用,总结,尊重知识产权。
参考博客:这个帖子写的非常好,
参考下
- 设计模式---工厂模式,我的理解,总结
- 我理解的设计模式:工厂模式
- 工厂模式--我的理解
- 设计模式-工厂模式的理解
- 我对工厂模式的理解
- 我对抽象工厂模式的理解
- 我理解的设计模式
- 设计模式,我理解的代理模式
- 设计模式之简单工厂的理解
- 工厂设计模式的简单理解
- 我理解的设计模式——总结
- 我总结的设计模式
- 工厂设计模式及理解
- C#----设计模式接口 工厂模式的理解
- 个人对于PHP设计模式之工厂模式的理解
- 设计模式之abstract factory工厂模式的理解
- 工厂模式的理解
- 工厂模式的理解
- 系统启动——Linux
- 需求评审阶段和设计评审阶段测试人员该做什么呢
- matlab中的log()
- struct kset
- 论文笔记之:Let there be Color!: Joint End-to-end Learning of Global and Local Image Priors for Automatic
- 设计模式---工厂模式,我的理解,总结
- c语言程序设计现代方法---第一章:C语言概述
- 加薪谈判注意要点
- 理解对象
- 整合ssh时 犯的愚蠢问题
- Codeforces Round #401 (div. 2) A,B,C,D
- Java设计模式之单例模式
- 这一次不写什么知识博客,就遇到的学习过程中的问题简要概述一下,算是给自己做个归纳总结吧
- PAT甲级C语言.1009. 说反话