前言:复习的时候把所有模式写了一遍,这里顺便就全部粘出来,讲解简单易懂为主
目录
可复用
Structural patterns
Adapter
适配器模式,顾名思义,像插头一样,国内外插头不一样,需要一个转化器,这里是参数不一样,同样需要一个转换类,直接看例子吧:
我们现在有一个接口,让两个数相加,参数就是这两个数:
public interface cpu {
public int add(int a,int b);
}
我们有一个实现类,但他的参数与接口有点不一样:
public class cpu1 {
/**
* 两个数相加
* @param a 第一个数
* @param c 第二个数比第一个数多的值
* @return 两个数相加的值
*/
public int add(int a,int c) {
return a+a+c;
}
}
这时我们就需要另外一个类对我们的参数稍微转化一下,然后委托给我们已有的实现类处理:
public class cpuAdapter implements cpu{
@Override
public int add(int a, int b) {
return new cpu1().add(a, b-a);
}
}
客户端:
public class Client {
public static void main(String[] args) {
cpu cpu = new cpuAdapter();
System.out.println(cpu.add(2, 2));//输出4
}
}
Decorator
装饰器模式,我一般习惯称为千层饼模式,有一个共同接口,然后一个主要类来实现这个接口基本功能,一个装饰抽象类实现接口,然后及其他具体装饰类也继承这个抽象类,不过会委托另一个实现类来做一些操作。![在这里插入图片描述]
下面实例:
同样是上面cpu的例子,有一个加法功能,只不过这次cpu1参数正常了,接口和具体实现类如下:
public interface cpu {
public int add(int a,int b);
}
public class cpu1 implements cpu{
@Override
public int add(int a,int b) {
return a+b;
}
}
然后所以装饰类的父类,一个抽象类,用来调用其他类的方法:
public abstract class cpuDecorator implements cpu{
protected final cpu cpu;//这里我们保存一个cpu对象,来作为我们要装饰的类
public cpuDecorator(cpu cpu) {
this.cpu = cpu;
}
public int add(int a,int b) {
return cpu.add(a, b);//委托给要装饰的完成本来的功能
}
}
这时,你突然想要add的时候多一个功能,就是输出参数a的值,这里我们写一个装饰类实现接口,然后委托cpu1:
public class cpu1Decorator1 extends cpuDecorator implements cpu{
public cpu1Decorator1(cpu cpu) {//构造时动态传入
super(cpu);
}
@Override
public int add(int a, int b) {
System.out.println(a);//我装饰的功能,可以输出a的值
return super.add(a, b);
}
}
这时我还想要个功能,可以输出b,同样的套路,我们再造个装饰类:
public class cpu1Decorator2 extends cpuDecorator implements cpu{
public cpu1Decorator2(cpu cpu) {//构造时动态传入
super(cpu);
}
@Override
public int add(int a, int b) {
System.out.println(b);//我装饰的功能,可以输出b的值
return super.add(a, b);//委托给要装饰的完成本来的功能
}
}
主角到齐了,那么怎么用呢,这里我们通过不断new来构建一个完成所有功能的类,也就是套娃,客户端代码:
public class Client {
public static void main(String[] args) {
cpu finishedCpu = new cpu1Decorator2(new cpu1Decorator1(new cpu1()));//从里往外装饰
System.out.println(finishedCpu.add(1, 2));//输出2 1 3
}
}
Facade
外观模式,让客户能用一个接口完成使用多个接口的复杂操作,说白了就是操作的打包整合,让客户更方便。
看上面的cpu,只有两个数的加法,客户要3个数相加,要用两次add,这很麻烦,所以我们再写个add功能用于3个数相加:
public interface cpu {
public int add(int a,int b);
public int add(int a,int b,int c);//添加一个方法3个数相加
}
public class cpu1 implements cpu{
@Override
public int add(int a, int b) {
return a+b;
}
@Override
public int add(int a, int b, int c) {
return add(c, add(a, b));//帮客户调用两次add,方便操作
}
}
Behavioral patterns
Strategy
策略模式,类似黑盒框架,说白了就是换种实现方式,一个接口多个子类,想用哪个用哪个,看例子:
还是上面cpu接口,只有一个add方法,我们把add委托出去:
public interface cpu {
public int add(int a, int b,cpuadd cpuadd);//这里动态传入cpuadd计算
}
public class cpu1 implements cpu{
@Override
public int add(int a, int b, cpuadd cpuadd) {
return cpuadd.add(a, b);//委托给cpuadd计算
}
}
这次我们有两种实现方式,一种是a+b,一种是a-5+b+5:
public interface cpuadd {
public int add(int a, int b);
}
public class cpuadd1 implements cpuadd{
@Override
public int add(int a, int b) {
return a+b;
}
}
public class cpuadd2 implements cpuadd{
@Override
public int add(int a, int b) {
return a-5+b+5;
}
}
这样我就有两个实例了,计算加法时根据情况选择对应类实例化即可:
cpu cpu = new cpu1();
int a = cpu.add(1, 2, new cpuadd1());
int b = cpu.add(2, 2, new cpuadd2());
System.out.println(a);//输出3
System.out.println(b);//输出4
Template Method
模板模式,跟白盒框架类似,主要流程已经在抽象类中设/计好了,每个具体功能为抽象方法,丢给子类实现,下面例子:
还是用cpu接口,这里我们先弄个模板出来,add分三个方法实现:
public abstract class cpuabstract implements cpu{
@Override
public int add(int a,int b) {//必须按一定的顺序执行
step1(a);
step2(b);
return step3(a,b);
}
public abstract void step1(int a);//我们要重写的具体操作
public abstract void step2(int b);
public abstract int step3(int a,int b);
}
然后写个子类继承,分别实现3个抽象方法:
public class cpu1 extends cpuabstract{
@Override
public void step1(int a) {
System.out.println(a);
}
@Override
public void step2(int b) {
System.out.println(b);
}
@Override
public int step3(int a, int b) {
System.out.println(a+b);
return a+b;
}
}
最后使用我们new子类就行了
public class Client {
public static void main(String[] args) {
cpu cpu = new cpu1();
cpu.add(1, 2);//输出1 2 3
}
}
Iterator
迭代器模式,java里就是实现Iterable接口和Iterator接口,下面一个存String的集合:
public interface collection extends Iterable<String>{
}
public class collectionimple implements collection{
private List<String> a;
public collectionimple(List<String> a) {
this.a = a;
}
@Override
public Iterator<String> iterator() {//Iterable的方法
return new collectionIterator(a);//这个Iterator的实现类,自己写,其实就用List的iterator挺好。
}
}
下面实现Iterator类,就是实现3个方法:
public class collectionIterator implements Iterator<String>{
private List<String> a;
private int i;
public collectionIterator(List<String> a) {
this.a = a;
i=-1;
}
@Override
public boolean hasNext() {
return i!=(a.size()-1);
}
@Override
public String next() {
if(hasNext()) {
i++;
return a.get(i);
}
throw new NoSuchElementException();
}
@Override
public void remove() {
a.remove(i);
i--;
}
}
客户端就可以用iterator遍历了:
public class Client {
public static void main(String[] args) {
List<String> aList = new ArrayList<String>();
aList.add("1");
aList.add("2");
collection collection = new collectionimple(aList);
Iterator<String> it = collection.iterator();
while (it.hasNext()) {
System.out.println(it.next());
it.remove();
}
//输出1 2
}
}
可维护
Creational patterns
Factory Method pattern
工厂方法模式,就是创建实例时用来隐藏具体类,把实例化这一过程放在方法中实现,下面例子:
一个创建上面cpu的工厂:
public interface cpuFactory {
public cpu createCpu1();
public cpu createCpu2();
}
public class cpuFactroyimple implements cpuFactory{
@Override
public cpu createCpu1() {
return new cpu1();
}
@Override
public cpu createCpu2() {
return new cpu2();
}
}
这样我们实例化工厂调用对应方法就可以创建对应cpu:
cpuFactory cpuFactory = new cpuFactroyimple();
cpu cpu1 = cpuFactory.createCpu1();
cpu cpu2 = cpuFactory.createCpu2();
当然这里我们还要实例化工厂方法,比较麻烦,所以一般用静态工厂方法:
public interface cpuFactory {
static public cpu createCpu1() {
return new cpu1();
}
static public cpu createCpu2() {
return new cpu2();
}
}
这样就不用实例化工厂方法了:
cpu cpu1 = cpuFactory.createCpu1();
cpu cpu2 = cpuFactory.createCpu2();
Abstract Factory
抽象工厂模式,说白了就是提供一种搭配,可以创建不同类型的类,但是要有一定搭配,例子:
这里我们引入gpu,也是有两种实现类,然后我们规定,cpu1和gpu1是一对,cpu2和gpu2是一对,然后这里我们用两个静态工厂方法:
public class computerFactory1 {
static public cpu createcpu() {
return new cpu1();
}
static public gpu creategpu() {
return new gpu1();
}
}
public class computerFactory2 {
static public cpu createcpu() {
return new cpu2();
}
static public gpu creategpu() {
return new gpu2();
}
}
这样是帮助客户进行搭配
Structural patterns
Proxy
代理模式,跟适配器模式有点像,使用一个类来做中转,当我们这个类创建时需要大量代价,我们就可以弄个中间类,使得我们可以在使用方法时再创建对应实现类来支付代价,也就是说我们一开始的代价降低,例子:
这里cpu有一个加法功能,我们实现化时要输入两个参数,下面这个实现类会自动相加保存起来:
public interface cpu {
public int add();
}
public class cpu1 implements cpu{
private int c;
public cpu1(int a,int b) {
c = a + b;//创建时相加
}
@Override
public int add() {
return c;
}
}
我们想创建时快一点,在我们调用方法时再相加,这里相当于做了个延迟委托:
public class cpuProxy implements cpu{
private int a;
private int b;
public cpuProxy(int a,int b) {//先存起来,不做任何操作
this.a = a;
this.b = b;
}
@Override
public int add() {
return new cpu1(a, b).add();//调用方法时再实例化对应类
}
}
客户端:
cpu cpu = new cpuProxy(1, 2);
System.out.println(cpu.add());//输出3
Behavioral patterns
Observer
观察者模式,1对多模式,实现类似粉丝和博主之间的关系,博主更新,他的粉丝的动态也会随之更新,下面例子:
实现up主和他的粉丝们的关系,管理先写接口:
public interface up {
public void addObserver(Observer observer);//添加粉丝
public void setState(String string);//更新状态
public String getState();
public void notifyObservers();//提醒粉丝
}
public interface Observer {
public void update(up up);//这里简单实现只关注一个up,只有update
}
下面一个up的实现:
public class up1 implements up{
private String s;//状态
private List<Observer> observers = new ArrayList<Observer>(); //粉丝集合
public up1(String string) {
setState(string);
}
@Override
public void addObserver(Observer observer) {
observers.add(observer);
}
@Override
public void setState(String string) {
s = string;
notifyObservers(); //每次更新完提醒粉丝
}
@Override
public String getState() {
return s;
}
@Override
public void notifyObservers() {
for(Observer observer : observers) {
observer.update(this);//调用粉丝的update方法实现更新
}
}
}
一个粉丝的实现:
public class observer1 implements Observer{
private up up;//存关注的up
public observer1(up up) {
this.up = up;
up.addObserver(this);//调用up的addObserver方法添加自己
}
@Override
public void update(up up) {
System.out.println(up.getState());//每次更新打印up状态
}
}
客户端:
up up = new up1("start");
new observer1(up);
new observer2(up);
up.setState("frist info");//输出两次frist info
up.setState("second info");//输出两次second info
上面是从头开始自己写,java还提供了具体实现类Observable和接口Observer来帮助我们写观察者模式,其内部具体实现看下面链接:
链接: Observer和Observable详解.
下面按上面的例子实际操作一下:
先写up的实现类:
public class up extends Observable{
private String state;//状态
public up(String string) {
state = string;
}
public void setstate(String string) {
state = string;
setChanged();//表示发生了变化
notifyObservers();
}
public String getstate() {
return state;
}
}
粉丝的类:
public class Observer1 implements Observer{
private up up;
public Observer1(up up) {
this.up = up;
up.addObserver(this);//添加粉丝
}
@Override
public void update(Observable o, Object arg) {
up up = (up) o;//转化成具体up
System.out.println(up.getstate());
}
}
客户端与上面一致,简单地使用很方便,但Observable毕竟是具体类,有局限性。
Visitor
这个模式就是给程序预留一个位置,来增加功能,其特点是从外部访问ADT,也就是说只能使用public的内容,直接看例子:
我们cpu只有加两个数的功能,我们现在扩展一个3个数相加的功能,首先cpu的接口要预留一个accept方法:
public interface cpu {
public int add(int a,int b);
public int accept(cpuVisitor visitor);//用来适应变化的
}
public class cpu1 implements cpu{
@Override
public int add(int a, int b) {
return a+b;
}
@Override
public int accept(cpuVisitor visitor) {
return visitor.visit(this);//我们的visitor只有一个方法visit来对cpu做处理
}
}
然后是visitor,这里感觉有点像外放的Facade模式一样:
public interface cpuVisitor {
public int visit(cpu cpu);//只有一个方法
}
public class cpuVisitor1 implements cpuVisitor{
private int a;
private int b;
private int c;
public cpuVisitor1(int a,int b,int c) {
this.a = a;
this.b = b;
this.c = c;
}
@Override
public int visit(cpu cpu) {
return cpu.add(c, cpu.add(a, b));//我们调用cpu的方法来实现
}
}
客户端:
cpu cpu = new cpu1();
int a = cpu.accept(new cpuVisitor1(1, 2, 3));//我们动态传入对应的visitor对象来实现不同的功能;
System.out.println(a);//输出6
State-based construction
State Pattern
状态模式之前写了一种,现在再写一种写法,例子:
红绿灯有3种状态,red,yellow,green可以依次循环转换,我们来分别设计3种状态的ADT及接口:
public interface State {
public State move();//下一个状态
public String getState();
}
public class red implements State{
static public red instance = new red();//只实例化一次
private red() {}//不让构造
@Override
public State move() {
yellow.a = 0;//让黄灯下次转成绿灯
return yellow.instance;//返回黄灯实例
}
@Override
public String getState() {
return "red";
}
}
public class yellow implements State{
static public yellow instance = new yellow();//只实例化一次
static public int a = 1;//用来判断该转为红灯还是绿灯
private yellow() {}//不让构造
@Override
public State move() {
switch (a) {//选择转成什么灯
case 1:
return red.instance;
default:
return green.instance;
}
}
@Override
public String getState() {
return "yellow";
}
}
public class green implements State{
static public green instance = new green();//只实例化一次
private green() {}//不让构造
@Override
public State move() {
yellow.a = 1;
return yellow.instance;
}
@Override
public String getState() {
return "green";
}
}
然后我们就可以通过委托的方式拿来用了,这里造一个light类来使用一下:
public class light {
private State s;
public light(State s) {
this.s = s;//初始化
}
public void move() {
s = s.move();//实现转化
}
public void getState() {
System.out.println(s.getState());
}
}
客户端:
light light = new light(red.instance);
light.getState();//输出red
light.move();
light.getState();//输出yellow
light.move();
light.getState();//输出green
light.move();
light.getState();//输出yellow
light.move();
light.getState();//输出red
Memento Pattern
备忘录模式,用来记录历史状态,好回滚,我们需要两个类,一个Memento类,用来保存一次状态,一个Caretaker类,用来保存历史状态合集,我们就在上面的状态模式例子中改造:
先写Memento
public class Memento {
State state;
public Memento(State state) {
this.state = state;
}
public State getState() {
return state;//取出state回滚
}
}
Caretaker:
public class Caretaker {
private List<Memento> mementos = new ArrayList<Memento>();
public void addMemento(Memento memento) {//添加一个历史版本
mementos.add(memento);
}
public Memento getMemento(int i) {//回滚到前i个版本
if(mementos.size()-i>=0) {
int a = mementos.size();
Memento memento = mementos.get(a-i);
for(int j = a-1;j>=a-i;j--) {
mementos.remove(j);//把回滚的版本删掉
}
return memento;
}
throw new RuntimeException("Cannot rollback so many back!");
}
}
我们在写个light2继承light,增添功能,light的State改为protected
public class light2 extends light{
public light2(State s) {
super(s);
}
public Memento save() {//存储现在的版本
return new Memento(s);
}
public void restore(Memento memento) {//回滚
s = memento.getState();
}
}
客户端:
light2 light2 = new light2(red.instance);
Caretaker caretaker = new Caretaker();
caretaker.addMemento(light2.save());
light2.move();
light2.getState();//输出yellow
light2.restore(caretaker.getMemento(1));
light2.getState();//输出red