软件构造系列(十一)可复用和可维护设计模式总结

前言:复习的时候把所有模式写了一遍,这里顺便就全部粘出来,讲解简单易懂为主

可复用

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
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值