设计模式之见解一

来源:互联网 发布: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()调用的是Objectclone()方法,Objectclonenative的。

浅复制:将一个对象复制后,基本数据类型的变量都会重新创建,而引用类型,指向的还是原对象所指向的,复制的不彻底。

深复制:将一个对象复制后,不论基本数据类型还是引用类型,都是重新创建的。复制的完全更新。

要实现深复制,需要采用流的形式读入当前对象的二进制输入,再写出二进制数据对应的对象。

0 0