【JAVA】 设计模式

https://blog.csdn.net/jack__chiang/article/details/70208886

1.设计模式的分类

创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代器模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
 

1.工厂模式(Factory Method):

  •     普通工厂模式
  •     多个工厂方法模式
  •      静态工厂方法模式

 1.1 普通工厂模式:

   如果存在多个类实现了同一个接口,则这些类的实例化统一在一个”工厂类“中进行:

  

    // 1. 发送短信和邮件的接口
    public interface Sender {  
        public void Send();  
    } 

    //2.1 . 发送邮件的实现类
    public class MailSender implements Sender {  
        public void Send() {  
            System.out.println("发送邮件!");  
        }  
    }  

    //2.2 . 发送短信的实现类
    public class SmsSender implements Sender {  
        public void Send() {  
            System.out.println("发送短信!");  
        }  
    }

    // 3   创建工厂类
    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();  
        }  
    } 

            

1.2 多个工厂模式

在普通方法模式基础上,直接在工厂类中提供创建类实例的方法,而不需要先筛选下发字符:

//将上面的代码做下修改,改动下SendFactory类就行
    //这个就不用根据用户传的字符串类创建对象了
    public class SendFactory {  

        public Sender produceMail(){  
            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();  
        }  
    }  

1.3 静态工厂方法模式

将上面多个工厂方法模式的方法设置为静态,不需要创建实例,直接调用:

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

总结:涉及到实现了一个接口的多个类的实例化时,创建一个“工厂类”,统一管理这些类的实例化过程;

 2.抽象工厂模式:

把“工厂类”抽象化:

    例子:
    //发送短信和邮件的接口
    public interface Sender {  
        public void Send();  
    } 

    //发送邮件的实现类
    public class MailSender implements Sender {  
        public void Send() {  
            System.out.println("发送邮件!");  
        }  
    }  
    //发送短信的实现类
    public class SmsSender implements Sender {  
        public void Send() {  
            System.out.println("发送短信!");  
        }  
    }  

    //给工厂类一个接口
    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();  
        }  
    }  

    //测试类
    public class Test {  

        public static void main(String[] args) {  
            //实例化一个工厂类
            Provider provider = new SendMailFactory(); 
            // 通过工厂类实例化需要创建的类 
            Sender sender = provider.produce();  
            sender.Send();  
        }  
    } 

总结:之前是一个工厂类可以实例化多个最终类,现在是多个工厂类,每个工厂类仅仅就实例化一个最终类,把最终类的多样性转移到工厂类的多样性上;

           简单点说,类似于利用多态性,如果B extends A ,B 中重写的A 中的方法,在创建A 时调用 A a = new B(); 则后续对a 的方法的调用实际上调用B 中的;

              Provider provider = new SendMailFactory();  Provider 是一个抽象类,provider 是一个抽象类的实例化对象,如果向修改provider 以后的操作,可以就修改 new 后面的方法,增加拓展性!!!!

其实还可以写一个类,继承SendMailFactory?

3.单例模式(Singleton)

  在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在。这样的模式有几个好处:

  1.减少反复创建同一个类的系统压力;

  2.省去new ,减轻GC;

//TODO

4.建造者模式(Builder)

google 源码中很常见的模式, 类在创建一个再一步步“填写”它的成员变量,方法;

class A {
   int a;
   long b;
   string c;

   void set_a(int new_a){ ... }
   void set_b(long new_b){ ... }
   ...
   ...
   int get_a();
   long get_b();
   ...
}

5.原型模式(Prototype)

将一个对象作为原型,对其进行复制、克隆,产生一个和原对象类似的新对象。在Java中,复制对象是通过clone()实现的:

    public class Prototype implements Cloneable {  

        public Object clone() throws CloneNotSupportedException {  
            Prototype proto = (Prototype) super.clone();  
            return proto;  
        }  
    } 

一个原型类,只需要实现Cloneable接口,覆写clone方法,此处clone方法可以改成任意的名称,因为Cloneable接口是个空接口,你可以任意定义实现类的方法名,如cloneA或者cloneB,因为此处的重点是super.clone()这句话,super.clone()调用的是Object的clone()方法,而在Object类中,clone()是native的,说明这个方法实现并不是使用java语言
//TODO  FURTHER DISCUSSING

结构型模式

6.适配器模式(Adapter)

6.0 类的适配器模式

    A extends B implement C

这样A 的实例对象中,既可以调用B中实现的方法,也可以调用C 的方法。如果B 和C 需要进行通信,就可以直接在A中进行参数处理;

6.1 对象适配器模式

类似于

class A implement C {

   public A( B b){
       this.b = b;
   }
}

 B 是A的构造参数,在A 的实例对象里可以直接调用B的信息,同时A 是C的实现类,A 中也可以调用C 的参数,最终B/C 通信;

6.2 接口适配器模式

A 为接口类, B 为抽象类且同时实现了A ,C extends B,重写方法

public interface A {
    public void method_A();
}

public abstract B implement A {
    public void method_A(){
        ....
    };
}

class C extends B {
    // 重写
    public void method_A(){
        ....
    };
    public void method_C(){
      ... ...
    }
}

三种适配器模式的总结:

  1. 类的适配器模式:当希望将一个类转换成满足另一个新接口的类时,可以使用类的适配器模式;
  2. 对象的适配器模式:当希望将一个对象转换成满足另一个新接口的对象时,可以创建一个新类,持有原类的实例,在新类中调用实例的方法即可;
  3. 接口的适配器模式:当不希望实现一个接口中所有的方法时,可以创建一个抽象类,实现接口所有的方法,我们写别的类的时候,继承抽象类;

7.装饰模式(Decorator):实现对已知类中定义方法的动态扩展

接口A 可以作为起实现类C 的构造参数,因此接口A 的另一实现类B 也可以作为C(及起子类)的构造参数,最终实现对接口A 定义的方法 func_A()  的动态 新增功能;

注: 这里类B 和 类C 都必须实现同一个接口A,才能实现最后调用func_A() 时,与运行的代码同时包含B和C 中对func_A 的重写。

public interface A {
    public void func_A();
}


public class B implements A {

    public void func_A() {
        ... ...
    }
}


public abstract class C implements A {

    private A a;
    public C(A a) {
       this.a = a;
    }
    
    public void func_A() {
        this.a.func_A();
    }
}


public class D1 extends C {
    public D1(A a){
        super(a);
    }

    public void func_A (){
        func_D1();
        super.func_A ();
    }

    public void func_D1() {
      ... ...
    }
}



public class D2 extends C {
    public D2(A a){
        super(a);
    }

    public void func_A (){
        super.func_A ();
        func_D2();
    }

    public void func_D2() {
      ... ...
    }
}


  testing code   ///



public class test {


   A test_a = new D2(new D1(new B()));

   test_a.func_A();

}

  A a = new D2(new D1(new B()));

 因为 D1 和D2 都是extends C,而C的构造函数中,可以保存一个A的实例作为C 自己的一个变量, 所以B(实现C) 和 D1/D2 都可以作为D1/D2 的形参

所以test_a.func_A(); 最后的运行是   

D2::func_A()

---> 1 .  D1::func_A() --->1.1 D1::func_D1()

                                   ---->1.2 B::func_A()

      2 .   D2::func_D2()

最后的运行结果是: func_D1() +B::func_A() ,+func_D2()  最终实现了 将func_A() 扩展的目的。

8 . 代理模式(Proxy)

  B 类 和 C 类同时实现接口A , B类是实例为c 类的实参,在C类中重写func_A , 最后A a = new C(); 达到C类重写的func_A 对B  类的func_A 进行拓展

    public interface A {  
        public void func_A();  
    }    

    public class B implements A{  

        public void func_A() {  
            ... ...  
        }  
    }

    public class C implements A {  

        private A a;  
        public C (A a){  
            this.a = a;  
        }  
        public void func_A() {  
            before();  
            a.func_A();  
            atfer();  
        }  
        private void func_C1() {  
            System.out.println("after proxy!");  
        }  
        private void func_C2() {  
            System.out.println("before proxy!");  
        }  
    } 


/testing code///

    public class test{  
        public static void main(String[] args) {  
            B b = new B();
            C c = new c(b);  
            c.func_A();  
        }  
    } 

 1.被代理的对象作为proxy类的实参,保证proxy类中有被带代理类的实例,进而对被代理类中func 进行拓展;

 2. 因为被代理类和代理类都是同一个接口的实现,根据多态实现类之间的“转换”;

1.静态代理类

有程序员创建或者由特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class 文件就已经存在;

2.动态代理类: 在程序运行时,运用反射机制动态创建而成

动态代理类的字节码在程序运行时由java反射制动动态生成,无需程序员手工编写它的源代码。

静态代理

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值