常用的几种设计模式

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();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值