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(){
... ...
}
}
三种适配器模式的总结:
- 类的适配器模式:当希望将一个类转换成满足另一个新接口的类时,可以使用类的适配器模式;
- 对象的适配器模式:当希望将一个对象转换成满足另一个新接口的对象时,可以创建一个新类,持有原类的实例,在新类中调用实例的方法即可;
- 接口的适配器模式:当不希望实现一个接口中所有的方法时,可以创建一个抽象类,实现接口所有的方法,我们写别的类的时候,继承抽象类;
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反射制动动态生成,无需程序员手工编写它的源代码。
静态代理