设计模式(二)之Strategy、Template and Iterator

论坛 期权论坛 编程之家     
选择匿名的用户   2021-6-2 17:12   3796   0

二、Behavioral patterns(行为型模式)

1.Strategy,策略模式

在策略模式中,一个类的行为或算法可以在运行时更改。在策略模式中,我们创建表示各种模式的对象和一个行为随着策略对象改变而改变的 context对象,策略对象改变 context对象的执行算法。


优点:算法可以自由切换、避免使用多重条件判断、扩展性良好

缺点:策略类会增多、所有策略类都需要对外暴露。

解决方法:将这些算法封装成一个一个的类,任意地替换

关键代码:实现同一个接口,如下面例子中CentralityStrategy接口

如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。

看下面这个例子:

对于一个图,我们可以计算图中顶点的不同类型的中心度,如degreeCentrality(点度中心度)、closenessCentrality(接近中心度)和betweenCentrality(中介中心度)。

我们按照上面的图来进行设计,首先给出Centrality接口:

CentralityStrategy.java

public interface CentralityStrategy {    //对应上图的 Strategy<<interface>>
    public abstract centrality();
}

然后通过三个具体的实现类来实现这个接口:

degreeCentralityStrategy.java

public class degreeCentralityStrategy<L extends Vertex, E extends Edge> implements CentralityStrategy {
 
 private final Graph<L, E> g;
 private final L v;
 
 public degreeCentralityStrategy(Graph<L, E> g, L v) {
  this.g = g;
  this.v = v;
 }
 
 @Override
 public double centrality() {
  return GraphMetrics.degreeCentrality(g, v);
 }
}
closenessCentralityStrategy.java
public class closenessCentralityStrategy<L extends Vertex, E extends Edge> implements CentralityStrategy {

 private final Graph<L, E> g;
 private final L v;
 
 public closenessCentralityStrategy(Graph<L, E> g, L v) {
  this.g = g;
  this.v = v;
 }
 
 @Override
 public double centrality() {
  return GraphMetrics.closenessCentrality(g, v);
 }
}
betweennessCentralityStrategy.java
public class betweennessCentralityStrategy<L extends Vertex, E extends Edge> implements CentralityStrategy{
 
 private final Graph<L, E> g;
 private final L v;
 
 public betweennessCentralityStrategy(Graph<L, E> g, L v) {
  this.g = g;
  this.v = v;
 }
 
 @Override
 public double centrality() {
  return GraphMetrics.betweennessCentrality(g, v);
 }
}
然后实现一个Context类 centralityContext.java
public class CentralityContext {
 
 public double centrality(CentralityStrategy centralityType) {
  return centralityType.centrality();
 }
}
可以使用Context来查看当它改变策咯Strategy时的行为变化,如下Main.java
public class Main {

 public static void main(String[] args) {

  Graph<Vertex, Edge> graph = GraphFactory.createGraph("test/graph/GraphPoetTest.txt");
  String[] strings = {"F", "24"};
  Vertex vertex1 = VertexFactory.createVertex("to", "Word", strings);
  CentralityContext context = new CentralityContext();
  double degree = context.centrality(new DegreeCentralityStrategy<>(graph, vertex1));
  double closeness = context.centrality(new ClosenessCentralityStrategy<>(graph, vertex1));
  double betweenness = context.centrality(new BetweennessCentralityStrategy<>(graph, vertex1));
  System.out.println(degree);
  System.out.println(closeness);
  System.out.println(betweenness);
 }
}

2.Template,模板模式

在模板模式中,一个抽象类公开定义了执行它的方法的方式/模式,它的子类可以按照需要重写实现方法,但调用将以抽象类中定义的方法进行。

将共性的步骤在抽象类内公共实现,差异化的步骤在各个子类中实现,使用继承和重写来实现模板模式。

优点:封装不变部分,扩展可变部分;提取公共代码,便于维护;行为由父类控制吗,子类实现


现有如下抽象类:

Edge.java

public abstract class Edge {
 
 private final String label;
 private final double weight;
 
 //the constructor
 public Edge(String label, double weight) {
  this.label = label;
  this.weight = weight;
 }

public abstract boolean addVertices(List<Vertex> vertices);

public abstract boolean containVertex(Vertex v);

public abstract Set<Vertex> vertices();

创建扩展了上述类的实现类

DirectedEdge.java

public class DirectedEdge extends Edge{
 
 private Vertex source;
 private Vertex target;
 
 //the constructor
 public DirectedEdge(String label, double weight) {
  super(label, weight);
 }

        @Override
 public boolean addVertices(List<Vertex> vertices) {
  source = vertices.get(0);
  target = vertices.get(1);
  return true;
 }
 
 @Override
 public boolean containVertex(Vertex v) {
  return source.equals(v) || target.equals(v);
 }
 
 @Override
 public Set<Vertex> vertices() {
  Set<Vertex> set = new HashSet<Vertex>();
  set.add(source);
  set.add(target);
  return set;
 }

和 UndirectedEdge.java

public class UndirectedEdge extends Edge{

 private Vertex vertex1;
 private Vertex vertex2;
 
 public UndirectedEdge(String label, double weight) {
  super(label, weight);
 }
 
 @Override
 public boolean addVertices(List<Vertex> vertices) {
  vertex1 = vertices.get(0);
  vertex2 = vertices.get(1);
  return true;
 }
 
 @Override
 public boolean containVertex(Vertex v) {
  return vertex1.equals(v) || vertex2.equals(v);
 }
  
 @Override
 public Set<Vertex> vertices() {
  Set<Vertex> set = new HashSet<Vertex>();
  set.add(vertex1);
  set.add(vertex2);
  return set;
 }

3.Iterator,迭代器模式

这种模式用于顺序访问集合对象的元素,而又无需暴露该对象的内部表示。


Iterable接口:实现该接口的集合对象是可迭代遍历的。

public interface Iterable<T> {
    ……
    Iterator<T> interator();
}
//Iterator接口:迭代器
public interface Iterator<E> {
    boolean hasNext();
    E next();
}

实现方法:让自己的集合类实现Iterable接口,并实现自己的独特的Iterrator迭代器(hasNext, next……),允许客户端利用这个迭代器显示或隐式的迭代遍历。


创建接口

public interface Iterator {
   public boolean hasNext();
   public Object next();
}

public interface Iterable {
   public Iterator getIterator();
}

创建Iterable接口的实体类,该类需要实现自己独特的Iterator迭代器

public class NameRepository implements Iterable {
   public String names[] = {"Robert" , "John" ,"Julie" , "Lora"};

   @Override
   public Iterator getIterator() {
      return new NameIterator();
   }
    //实现自己独特的Iterator迭代器
   private class NameIterator implements Iterator {

      int index;

      @Override
      public boolean hasNext() {
         if(index < names.length){
            return true;
         }
         return false;
      }

      @Override
      public Object next() {
         if(this.hasNext()){
            return names[index++];
         }
         return null;
      }        
   }
}
使用迭代器来遍历集合元素:
    for(Iterator iter = namesRepository.getIterator(); iter.hasNext();){  //无需暴露内部表示
         String name = (String)iter.next();
         System.out.println("Name : " + name);
      }  




分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP