常用的几种设计模式

来源:互联网 发布:网络语言暴力视频 编辑:程序博客网 时间:2024/05/22 01:33

1.单例设计模式singleton——只能产生一个实例化对象的设计模式

(为什么不用静态变量代替呢?因为静态变量在程序一开始就创建了对象,可能会比较消耗资源)

public class Singleton {    private static Singleton uniqueInstance;    private Singleton(){}    public static Singleton getInstance(){        if(uniqueInstance == null){            uniqueInstance = new Singleton();        }        return uniqueInstance;    }}public class singletonTest {    public static void main(String args[]){        Singleton s1 = Singleton.getInstance();        Singleton s2 = Singleton.getInstance();        System.out.println("s1:" + s1 + ",s2:" + s2);    }}

运行结果显示:

s1:designPattern.Singleton@6f94fa3e,s2:designPattern.Singleton@6f94fa3e

两个对象的地址相同,表示只产生了一个实例化对象


2.工厂设计模式Factory将对象的创建封装起来

(1)简单工厂:程序中只有一个工厂,在工厂内部根据数据逻辑判断来创建不同对象

实例:假设有一个Sender接口,以及实现了这两个接口的类:MailSender和SmsSender

public interface Sender{    public void Send();}public class MailSender implements Sender{    public void Send(){        System.out.println("mailsender!");    }}public class SmsSender implements Sender{    public void Send(){        System.out.println("smssender!");    }}
现在设计一个简单工厂对象用于产生这两个类的实例化对象如下:

public class SendFactory{    public Sender produce(String type){        if("mail".equals(type)){            return new MailSender();        }else if("sms".equals(type)){            return new SmsSender();        }else{            return null;        }    }}
调用过程:

SendFactory sendproduct = new SendFactory();Sender send = sendproduct.produce("mail");
整个代码中只有一个工厂类,这就是简单工厂。


(2)工厂方法:针对于简单工厂的改进(由于传送数据出错导致返回null),对于每一种类设置一个工厂方法用于返回相应的对象。

工厂方法代码如下:

public class SendfunctionFactory{    public Sender produceMail(){        return new MailSender();    }    public Sender produceSms(){        return new SmsSender();    }}
调用过程:

SendfunctionFactory factory = new SendfunctionFactory();Sender send = factory.produceMail();
大部分情况下,都会对上述方法进行改进,即将上述工厂方法设置为静态的,这样,不实例化工厂对象也可以调用相应的工厂方法。


(3)抽象工厂:针对于工厂方法中的不足—当添加了一个子类时,需要在已有的工厂中添加一个方法,改变了已有的代码。改进:写一个工厂接口,每一个类都有一个相应的工厂实现该接口,当添加一个类的时候,只需要添加一个工厂类就行,不必修改已有的工厂类。

代码如下:

public interface provider{    public Sender produce();}public class SendMailFactory implements provider{    public Sender produce(){        return new MailSender();    }}public class SendSmsFactory implements provider{    public Sender produce(){        return new SmsSender();    }}
调用方式如下:

provider pro = new SendMailFactory();Sender sender = pro.produce();
调用时指明是哪个工厂。

3.适配器设计模式adapter—将一个种类型转换成另外一种适合场景的类型

(1)类的适配器模式:希望将一个类转换成满足另一个接口的新类。

创建一个新类,继承原有的类,实现新的接口

实例:假设有一个源类Source和一个目标接口Targetable

public class Source{    public void method1(){        System.out.println("source's method1");    }}public interface Targetable{    public void method1();    public void method2();}
现在想要通过适配器使source类可以实现目标接口,方式是,编写一个新类:

public class Adaptor extends Source implements Targetable{    public void method2(){        System.out.println("Adaptor's method2");    }}
调用的方式:

        Targetable target = new Adaptor();        target.method1();        target.method2();

(2)对象的适配器模式:希望将一个对象转换成一个新接口的对象

实现方式是,创建一个新类,该类包含一个原对象的属性,并且该类实现了接口中的方法。

public class Newclass implements Targetable{    private Source source;    public Newclass(Source source){        super();        this.source = source;    }    public void method1(){        System.out.println("newclass's method1");    }    public void method2(){        System.out.println("newclass's method2");    }}
使用方式,使用给定的对象构造适配器类:

        Source source = new Source();        Targetable target = new Newclass(source);        target.method1();        target.method2();


(3)接口适配器设计模式:有的时候一个接口中有很多种方法,我们在实现一个接口的时候,并不想使用所有的这些接口,就可以使用接口的适配器模式。

比如有一个接口有两个方法:

public interface Sourceable{    public void method1();    public void method2();}
现在想产生两个类,类1只想要方法1,类2只想要方法2,实现方式是先构建一个抽象类:

public abstract class newclass implements Sourceable{    public void method1(){}    public void method2(){}}
然后再让两个类继承该抽象类:

public class SourceSub1 extends newclass{    public void method1(){        System.out.println("sourcesub1's method1");    }}public class SourceSub2 extends newclass{    public void method2(){        System.out.println("sourcesub2's method2");    }}
由于继承时可以不必重写所有方法,所以两个子类只需要重写自己想用的方法即可,使用方式:

        Sourceable source1 = new SourceSub1();        Sourceable source2 = new SourceSub2();        source1.method1();        source1.method2();        source2.method1();        source2.method2();

4.装饰设计模式—给类添加新的功能

(为什么不用继承?因为继承时静态的,装饰设计模式可以动态的添加功能,避免了继承体系的臃肿)

对于一个类和一个接口,编写一个装饰类实现该接口,装饰类中含有源类的实例化对象。

如下,假设有一个接口SourceAble,和一个实现了该接口的类SourceClass:

public interface SourceAble{    public void method();}public class SourceClass implements  SourceAble{    public void method(){        System.out.println("source method");    }}
现在想丰富该类中method方法的功能,实现方式是编写一个装饰类:

public class DecoratorClass implements SourceAble{    private SourceAble source;    public DecoratorClass(SourceAble source){        super();        this.source = source;    }    public void method(){        System.out.println("before decorator");        source.method();        System.out.println("after decorator");    }}
使用方式:

        SourceAble source = new SourceClass();        SourceAble dec = new DecoratorClass(source);        dec.method();

(5)代理设计模式proxy—设计一个对象,该对象为另一个对象提供替身以控制该对象的访问,处理代理对象就像处理原始对象一样。(被代理的对象可以是远程对象、创建开销大的对象或者需要安全控制的对象)



代理模式和装饰模式的区别:

代理模式注重控制,原始的功能不变;

装饰模式注重功能的添加;

(个人觉得,在代码结构上没什么区别,主要区别是你这段代码的目的性)

动态代理模式— 一个代理类可以代理所有需要被代理接口(功能相似的接口)的子类对象

①JDK动态代理:代理的类实现了某一接口

用到了InvocationHandler接口

public interface InvocationHandler { public Object invoke(Object proxy,Method method,Object[] args) throws Throwable; } 
说明:

Object proxy:指被代理的对象。 
Method method:要调用的方法 
Object[] args:方法调用时所需要的参数 

用到了Proxy类: 
Proxy类是专门完成代理的操作类,可以通过此类为一个或多个接口动态地生成实现类,此类提供了如下的操作方法: 
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException 
参数说明: 
ClassLoader loader:类加载器 
Class<?>[] interfaces:得到全部的接口 
InvocationHandler h:得到InvocationHandler接口的子类实例 


实例代码如下:

interface BookFacade{    public void addBook();}class BookFacadeImpl implements  BookFacade{    public void addBook(){        System.out.println("add book");    }}class BookFacadeProxy implements InvocationHandler{//代理类实现InvocationHandler接口    private Object target;    public Object bind(Object target){//执行对象的绑定        this.target = target;        return Proxy.newProxyInstance(target.getClass().getClassLoader() ,target.getClass().getInterfaces(),this);    }    public Object invoke(Object proxy, Method method, Object[] args)throws  Throwable{//实现接口里面的invoke方法        Object result = null;        System.out.println("begin");        result = method.invoke(target,args);        System.out.println("end");        return result;    }}public class JDKProxy {    public static void main(String args[]){        BookFacadeProxy proxy = new BookFacadeProxy();        BookFacade bookProxy = (BookFacade)proxy.bind(new BookFacadeImpl());        bookProxy.addBook();    }}

②CGLIB动态代理:代理的类没有实现接口

public class BookFacadeCglib implements MethodInterceptor {      private Object target;        public Object getInstance(Object target) {          this.target = target;          Enhancer enhancer = new Enhancer();          enhancer.setSuperclass(this.target.getClass());          // 回调方法          enhancer.setCallback(this);          // 创建代理对象          return enhancer.create();      }        public Object intercept(Object obj, Method method, Object[] args,MethodProxy proxy) throws Throwable {          System.out.println("事物开始");          proxy.invokeSuper(obj, args);          System.out.println("事物结束");          return null;          }    }  

(6)观察者模式observer—当一个对象变化的时候,跟其相关联的对象中的相应值也会变化

需要有两个接口:Subjec(被观察的对象接口),Observer(观察者的接口):

public interface Observer{    public void update();}public interface Subject{    public void add(Observer observer);//用于增加观察者    public void del(Observer observer);//用于删除观察者    public void notifyObservers();//用于通知所有观察者    public void operation();}

定义一个抽象类实现被观察者接口:

public abstract class AbstractSubject implements Subject{    private List<myObserver> list = new ArrayList<myObserver>();    public void add(myObserver observer){        list.add(observer);    }    public void del(myObserver observer){        list.remove(observer);    }    public void notifyObservers(){        for(myObserver observer : list){            observer.update();        }    }}

定义两个观察者类以及一个被观察者类:

public class Observer1 implements myObserver{    public void update(){        System.out.println("Observer1's update");    }}public class Observer2 implements myObserver{    public void update(){        System.out.println("Observer2's update");    }}public class mySubject extends AbstractSubject{    public void operation(){        System.out.println("my operation");        notifyObservers();    }}
使用方法:

        Subject sub = new mySubject();        sub.add(new Observer1());        sub.add(new Observer2());        sub.operation();