设计模式之见解一
来源:互联网 发布:ecshop php 5.5 编辑:程序博客网 时间:2024/05/16 14:17
设计模式(Design Patterns)
使用设计模式是为了可以重用代码,让代码更加容易被他人理解、保证代码的可靠性。设计模式使得代码编制真正工程化,是软件工程的基石。
在项目中合理的运用设计模式可以完美的解决很多问题,每个模式在现在中都有相应的原理来与之对应。
一、设计模式的分类
总体的来说设计模式有三种类型:
创建型模式:工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式
结构型模式:适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组合模式,享元模式
行为型模式:策略模式,模板方法模式,观察者模式,迭代子模式,责任链模式,命令模式,备忘录模式,状态模式,访问者模式,中介者模式,解释器模式
还有两个独立的模式:并发型模式,线程池模式。
二、设计模式的原则
1】开闭原则(open Close principle)
开闭原则就是说对扩展开放,对修改关闭。在程序需要进行扩展的时候,不能去修改原有的代码,实现一个热插拔的效果。所以就是说:为了程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类。
2】里氏代换原则(Liskov Substitution Principle)
里氏代换原则是面向对象设计的基本原则之一。任何基类可以出现的地方,子类一定可以出现。LSP是继承复用的基石。只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。里氏代换原则是对“开闭原则”的补充。实现“开闭原则”的关键是抽象化。而基类与子类的继承关系就是抽象化的具体实现。
3】依赖倒转原则(Dependence Inversion Principle)
依赖倒转原则是开闭原则的基础,是对接口编程,依赖于抽象而不依赖于具体。
4】接口隔离原则(Interface Segregation Principle)
使用多个隔离的接口,比使用单个接口更好。还是一个降低类之间的耦合度,从大型软件架构出发,为了升级和维护方便。降低依赖和耦合度。
5】迪米特原则(最少知道原则)(Demeter Principle)
一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。
6】合成复用原则(Composite Reuse Principle)
是尽量使用合成/聚合的方式,而不是使用继承。
三、各个模式的运用
1】工厂方法模式(Factory Method)
工厂方法模式为三种:
普通工厂模式,为建立一个工厂类,对实现了同一接口的一些类进行实例的创建。
package com.mjf.model.factory; public interface Send { public void send();}package com.mjf.model.factory; /** * 工厂实现类 * @author h * */public class MailSender implements Send { @Overridepublic void send() {// TODO Auto-generated method stubSystem.out.println("this is mail send");} }package com.mjf.model.factory; /** * 工厂实现类 * @author h * */public class SmsSender implements Send { @Overridepublic void send() {// TODO Auto-generated method stubSystem.out.println("this is sms send");} }package com.mjf.model.factory; /** * 工厂类 * @author h * */public class SendFactory { public Send getSend(String type){if("sms".equals(type)){return new SmsSender();}else if("mail".equals(type)){return new MailSender();}else{System.out.println("请选择正确的类型");return null;}}}/** 测试类 */package com.mjf.test.factory; import com.mjf.model.factory.Send;import com.mjf.model.factory.SendFactory; public class FactoryTest01 { public static void main(String[] args) {SendFactory send = new SendFactory();Send s = send.getSend("mail");s.send();}}
多个工厂方法模式,是对普通工厂方法模式的改进,在普通工厂方法模式中,如果传递的字符串出错,则不能创建对象,而多个工厂方法模式是提供多个工厂方法,让他们分别创建对象。
package com.mjf.model.factory; /** * 工厂实现类 * @author h * */public class MailSender implements Send { @Overridepublic void send() {// TODO Auto-generated method stubSystem.out.println("this is mail send");} }package com.mjf.model.factory; public interface Send { public void send();}package com.mjf.model.factory; /** * 工厂实现类 * @author h * */public class SmsSender implements Send { @Overridepublic void send() {// TODO Auto-generated method stubSystem.out.println("this is sms send");} }package com.mjf.model.factory; /** * 工厂类(多个) * @author h * */public class SendFactory2 { public Send getSmsSend(){return new SmsSender();}public Send getMailSend(){return new MailSender();}}/** 测试类 */package com.mjf.test.factory; import com.mjf.model.factory.Send; import com.mjf.model.factory.SendFactory2; public class FactoryTest02 { public static void main(String[] args) {SendFactory2 send2 = new SendFactory2();//Send s = send2.getMailSend();Send s = send2.getSmsSend();s.send();}}
使用了多个工厂方法模式后,改进了可以在工厂实现类中添加方法来创建对象。
静态工厂方法模式,是将工厂方法模式里的方法设置为静态的,不需要创建实例可以直接调用。
package com.mjf.model.factory; /** * 工厂类(多个) * @author h * */public class SendFactory3 { public static Send getSmsSend(){return new SmsSender();}public static Send getMailSend(){return new MailSender();}}/** 测试类 */package com.mjf.test.factory; import com.mjf.model.factory.Send; import com.mjf.model.factory.SendFactory3; public class FactoryTest03 { public static void main(String[] args) {//Send s = SendFactory3.getMailSend();Send s = SendFactory3.getSmsSend();s.send();}}
总体来说,工厂模式的作用范围为:出现了很多的对象需要进行创建时,并且用相同的接口。则可以通过工厂方法模式进行创建。
2】抽象工厂模式(Abstract Factory )
工厂方法模式有一个问题是,类的创建依赖于工厂类,也就是说,如果要扩展程序就要对工厂类进行修改,违背了开闭原则。
所以采用抽象工厂模式,创建多个工厂类,当增加新的功能,直接增加新的工厂类就行了,而不需要修改原来的代码。
package com.mjf.model.abstract_factory; public interface Send { public void send();}package com.mjf.model.abstract_factory; /** * 工厂实现类 * @author h * */public class MailSender implements Send { @Overridepublic void send() {// TODO Auto-generated method stubSystem.out.println("this is mail send");} }package com.mjf.model.abstract_factory; /** * 工厂实现类 * @author h * */public class SmsSender implements Send { @Overridepublic void send() {// TODO Auto-generated method stubSystem.out.println("this is sms send");} }package com.mjf.model.abstract_factory; public class SmsFactory implements Provder { @Overridepublic Send getProduct() {// TODO Auto-generated method stubreturn new SmsSender();} }package com.mjf.model.abstract_factory; public class MailFactory implements Provder { @Overridepublic Send getProduct() {// TODO Auto-generated method stubreturn new MailSender();} }package com.mjf.model.abstract_factory; public interface Provder { public Send getProduct();} /** 测试类 */package com.mjf.test.abstract_factory; import com.mjf.model.abstract_factory.MailFactory;import com.mjf.model.abstract_factory.Provder;import com.mjf.model.abstract_factory.Send;//import com.mjf.model.abstract_factory.SmsFactory; public class AbstactFactoryTest { public static void main(String[] args) {//Provder pro = new SmsFactory();//Send product = pro.getProduct();//product.send();Provder pro = new MailFactory();Send s = pro.getProduct();s.send();}}
3】单例模式(singleton)抽象工厂模式的好处为:如果你现在想要增加一个功能,发及时信息,则只需要做一个实现类,实现send接口,做一个工厂类,实现provder接口,就可以了;无需去改动现成的代码。扩展性好。
单例对象是一种常用的设计模式。单例对象保证在jvm中,该对象只有一个实例存在。
单例的作用:1)某些类创建比较频繁,对于一些大型的对象,这是一笔很大的系统开销;2)省去了new操作符,降低了系统内存的使用频率,减轻GC的压力;3)有些类好像交易所的核心交易引擎控制交易的流程,如果该类可以创建多个的话,系统就会繁乱。
package com.mjf.model.singleton; public class Singleton { /** 持有私有静态实例,防止被引用,此处赋值为null,目的是实现延迟加载 */private static Singleton instance = null;/** 创建私有化构造方法。防止被初始化 */private Singleton(){}public static Singleton getInstance(){if(instance == null){instance = new Singleton();}return instance;}public Object getResolve(){return instance;}}
其实单例模式使用的内部类来维护单例的实现,JVM内部的机制能够保证当一个类被加载的时,这个类的加载过程是线程互斥的。这个类使用是可以实现单例模式,但是存在着线程安全问题。但是,如果使用了synchronize锁定的话,性能会有所下降,当每次调用方法的时候,就会去为对象锁上锁。
package com.mjf.model.singleton; public class Singleton02 { /** 创建私有化构造方法。防止被初始化 */private Singleton02(){}/** 创建内部类来实现单例 */private static class SingletonFactory {private static Singleton02 instance = new Singleton02();}public static Singleton02 getInstance(){return SingletonFactory.instance;}}
单例模式:
1、单例模式理解比较简单,但是实现有点难度。
2、Synchronized关键字锁定的是对象,在用的时候需要注意。
3、单例类比较灵活,毕竟从实现上只是一个普通的Java类,只要满足单例的基本需求,你可以在里面随心所欲的实现一些其它功能,但是静态类不行。从上面这些概括中,基本可以看出二者的区别,但是,从另一方面讲,我们上面最后实现的那个单例模式,内部就是用一个静态类来实现的,所以,二者有很大的关联,只是我们考虑问题的层面不同罢了。两种思想的结合,才能造就出完美的解决方案,就像HashMap采用数组+链表来实现一样,其实生活中很多事情都是这样,单用不同的方法来处理问题,总是有优点也有缺点,最完美的方法是,结合各个方法的优点,才能最好的解决问题!
4】建设者模式(Builder)
工厂模式提供的时创建单个类的模式,而建造者模式则是将各种产品集中起来进行管理,用来创建复合对象。所谓复合对象就是指某个类具有不同的属性;其实建造者模式就是工厂模式里面的对象创建多个进行管理。
package com.mjf.model.builder; import java.util.ArrayList;import java.util.List; public class Builder { private List<Send> list = new ArrayList<Send>();public void produceMailSender(int count){for(int i=0;i<count;i++){list.add(new MailSender());}}public void produceSmsSender(int count){for(int i=0;i<count;i++){list.add(new SmsSender());}}}package com.mjf.model.builder; import java.util.ArrayList;import java.util.List; public class Builder { private List<Send> list = new ArrayList<Send>();public void produceMailSender(int count){for(int i=0;i<count;i++){list.add(new MailSender());}}public void produceSmsSender(int count){for(int i=0;i<count;i++){list.add(new SmsSender());}}}package com.mjf.model.builder; /** * 工厂实现类 * @author h * */public class MailSender implements Send { @Overridepublic void send() {// TODO Auto-generated method stubSystem.out.println("this is mail send");} }package com.mjf.model.builder; /** * 工厂实现类 * @author h * */public class SmsSender implements Send { @Overridepublic void send() {// TODO Auto-generated method stubSystem.out.println("this is sms send");}}/** 测试类 */package com.mjf.test.builder; import com.mjf.model.builder.Builder; public class BuilderTest { public static void main(String[] args) {Builder builder = new Builder();builder.produceMailSender(10);}}
建造者模式将很多的功能集成到一个类里,这个类可以创造出比较复杂的东西。与工厂模式的区别:工厂模式关注的是创建单个产品,而建造者模式则关注创建符合对象。
5】原型模式(Prototype)
原型模式的思想是将一个对象作为原型,对其进行复制,克隆,产生一个和原对象类似的新对象。复制对象是通过clone()实现的,实现了Cloneable接口。
package com.mjf.model.prototype; import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.Serializable; public class Prototype02 implements Cloneable,Serializable { private static final long serialVersionUID = 1L;private String string;private SerializableObject obj;/** 浅复制 */public Object clone() throws CloneNotSupportedException{Prototype02 pro = (Prototype02) super.clone();return pro;}/** 深复制 */ public Object deepClone() throws IOException, ClassNotFoundException { /* 写入当前对象的二进制流 */ ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(this); /* 读出二进制流产生的新对象 */ ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bis); return ois.readObject(); } /** 内部类 */private class SerializableObject implements Serializable{ private static final long serialVersionUID = 1L;} /** setter and getter method */public String getString() {return string;}public void setString(String string) {this.string = string;} public SerializableObject getObj() {return obj;}public void setObj(SerializableObject obj) {this.obj = obj;}}
一个原型类,只需要实现Cloneable接口,复写clone方法,其实cloneable接口是个空接口,所以clone的方法名是随意取的。重点是super.clone()调用的是Object的clone()方法,Object的clone是native的。
浅复制:将一个对象复制后,基本数据类型的变量都会重新创建,而引用类型,指向的还是原对象所指向的,复制的不彻底。
深复制:将一个对象复制后,不论基本数据类型还是引用类型,都是重新创建的。复制的完全更新。
要实现深复制,需要采用流的形式读入当前对象的二进制输入,再写出二进制数据对应的对象。
- 设计模式之见解一
- 设计模式之个人见解
- 设计模式之见解二
- 设计模式之见解三
- 设计模式之外观模式见解
- 23种设计模式之有趣见解
- 23种设计模式之有趣见解
- C++中设计模式之我见解
- 单例设计模式之个人见解
- 设计模式-见解
- PHP设计模式之单例模式个人见解
- 【设计模式篇】Android设计模式之-组合模式 自我见解
- 【设计模式篇】Android设计模式之-策略模式 自我见解
- 【设计模式篇】Android设计模式之-观察者模式 自我见解
- 设计模式的有趣见解
- 设计模式.笔记.有趣见解
- java 设计模式有趣见解
- 【转】关于23种设计模式的有趣见解(一)
- js代码库
- 我的保研经历——中国科学院计算技术研究所(更新中。。)
- Android Bluetooth开发1
- 传统 vs 敏捷 ?第三方业务风控服务企业项目管理分析
- 快递查询 (快递100)
- 设计模式之见解一
- Linux 软件安装到 /usr,/usr/local/ 还是 /opt 目录?
- android app防被杀策略
- 盒子模型
- EventBus简单实用
- DOM事件
- 人脸识别(3)--EBGM
- HttpClient
- JEM Inter/Merge/Affine的MVP candidates的建立