哈工大软件构造Lab3

目录

1.实验目标概述

2.实验环境配置

3.实验过程

3.1待开发的三个应用场景

3.2基于语法的图数据输入

3.3面向复用的设计:CircularOrbit,e>

3.4面向复用的设计:Track

3.5面向复用的设计

3.7可复用API设计 

3.8图的可视化:第三方API的复用

3.9设计模式的应用

3.10应用的设计与开发 

3.10.2StellarSystem

3.10.3AtomicStructure

3.10.5SocialNetworkCircle

3.11应对应用面临的新变化

3.11.2StellarSystem

3.11.3AtomicStructure

3.11.5SocialNetworkCircle

 3.12Git仓库结构


1.实验目标概述

本次实验覆盖课程第 2、3 章的内容,目标是编写具有可复用性和可维护性的软件,主要使用以下软件构造技术:

        子类型、泛型、多态、重写、重载

        继承、委派、CRP

        语法驱动的编程、正则表达式

        设计模式

本次实验给定了多个具体应用,学生不是直接针对每个应用分别编程实现,

而是通过 ADT 和泛型等抽象技术,开发一套可复用的 ADT 及其实现,充分考虑

这些应用之间的相似性和差异性,使 ADT 有更大程度的复用(可复用性)和更

容易面向各种变化(可维护性)

2.实验环境配置

java环境已经配置完成,idea中可以下载Juint

在这里给出你的GitHub Lab3仓库的URL地址(Lab3-学号)。

3.实验过程

请仔细对照实验手册,针对每一项任务,在下面各节中记录你的实验过程、阐述你的设计思路和问题求解思路,可辅之以示意图或关键源代码加以说明(但千万不要把你的源代码全部粘贴过来!)。

3.1待开发的三个应用场景

首先请列出你要完成的具体应用场景(至少3个,1和2中选一,3必选,4和5中选一,鼓励完成更多的应用场景)。

  1. StellarSystem
  2. AtomicStructure
  3. SocialNetworkCircle

分析你所选定的多个应用场景的异同,理解需求:它们在哪些方面有共性、哪些方面有差异。

3.2基于语法的图数据输入

文件中系统的建立是以正则表达式的形式所建立的,所以针对不同的系统,我们有着不同表达式的建立

首先是恒星系统:

//恒星的表达式:
String P_Stellar = "Stellar ::= <" +
        "(?<name>[\\w]+)," +
        "(?<radius>[\\d]{1,4}[.]?[\\d]*[e]*[\\d]*)," +
        "(?<kilo>[\\d]{1,4}[.]?[\\d]*[e]*[\\d]*)>";
//行星的表达式:
String P_Planet = "Planet ::= <" +
        "(?<name1>[\\w]+)," +
        "(?<state>[\\w]+)," +
        "(?<color>[\\w]+)," +
        "(?<radius1>[\\d]{1,4}[.]?[\\d]*[e]?[\\d]*)," +
        "(?<radius2>[\\d]{1,4}[.]?[\\d]*[e]?[\\d]*)," +
        "(?<speed>[\\d]{1,4}[.]?[\\d]*[e]?[\\d]*)," +
        "(?<direction>[C]+[W])," +
        "(?<angle>[\\d]{1,4}[.]?[\\d]*[e]?[\\d]*)>";

原子系统:

//原子核表达式:
String P_Atom = "ElementName ::= (?<name>[\\w]+)";
//轨道数量表达式:
String P_Num = "NumberOfTracks ::= (?<num>[\\d])";
//电子轨道表达式:
String P_Electron = "NumberOfElectron ::= (?<orbit>([\\d][/][\\d]+[;]*)+)";

人际交往圈系统:

//中心用户表达式:
String P_CentralUser = "CentralUser ::= <(?<name>[\\w]+),(?<age>[\\d]+),(?<sex>[M|F])>";
//朋友表达式:
String P_Friend = "Friend ::= <(?<name>[\\w]+),(?<age>[\\d]+),(?<sex>[M|F])>";
//关系表达式:
String P_Relationship = "SocialTie ::= <(?<name1>[\\w]+),(?<name2>[\\w]+),(?<relation>[\\d][.][\\d]+)>";

以正则表达式读取的文件将会以字符串的形式储存起来,然后用匹配的方式去获得数据,转化成相应的数据,建立中心物体与轨道物体,然后建立系统将物体存放进去。

Pattern ptn = Pattern.compile(正则表达式);
Matcher matcher = ptn.matcher(要匹配的表达式);

3.3面向复用的设计:CircularOrbit<L,E>

建立接口CircleOrbit,其中接口的方法包括一下这些:

//产生空系统:
static <L,E> CircularOrbit<L,E> emptySystem(){
    return new ConcreteCircularOrbit<>();
}

//创造中心物体:
boolean creatCentralObject(L CentralObject,String name);

//添加轨道:
boolean addTrack(Track<E> track);

//移除轨道:
boolean removeTrack(Track<E> track);

//向特定轨道添加物体:
boolean addPhysicalObject(Track<E> track, E PhysicalObject); 
boolean  addPhysicalObject(Track<E> track, E PhysicalObject,String name);

//从系统移除物体:
boolean removePhysicalObject(E PhysicalObject);

//迁移物体:
void transit (E object, Track<E> track);

//读取文件:
void readFile(File file) throws IOException;

//移动角度:
void move(E object, double sitha);

//获得中心物体:
L getCentralObject();

//获得所有轨道物体:
Set<E> getPhysicalObjects();

//获得所有轨道:
Set<Track<E>> getAllTracks();

//获得某个物体所在轨道:
Track<E> getTrack(E PhysicalObject);

//获得某个轨道的全部物体:
Set<E> getTrackPhysicalObject(Track<E> track);

//获得读取文件后的数据:
String[] getString();

//获得所有物体的名字列表:
Map<Object,String> getName();

//设置两个物体间的关系:
boolean setRelationship(Object object1,Object object2,double num);

//获得两个物体间的关系:
double getRelationship(Object object1,Object object2);

//获得关系图:
Graph getGraph();

//设置关系图:
boolean setGraph(Graph graph);

//获得遍历器:
CircularOrbitIterator<E> iterator();

静态方法用来产生一个空的系统,其余的方法会在ConcreteCircleOrbit中实现

那么对于实现类来说,我们要定义如下的rep来完成我们所需要的操作:

private final Set<Track<E>> Tracks = new HashSet<>();
private L CentralObject=null;
private final Set<E> PhysicalObjects = new HashSet<>();
private final Map<Object,String> NameList = new HashMap<>();
private Graph Relationship = Graph.empty();
private String[] DataBase;

Tracks的用处是储存轨道的一个集合,CentralObject用来放置中心物体,其中对于不同的系统,会有不同的中心物体,所以我们用泛用性L来表示,轨道物体也用E来表示,PhysicalObjects用来储存所有的轨道物体,NameList用来储存每一个物体的名字,方便后续App中用户输入时,检索物体的操作减少代码量。

Relationsh是一个图的结构,在Lab2中我们已经实现了图的操作,不过在此次实验中,我们需要对图进行稍作更改,让其权重的数值变为double类型的数据,通过复用Lab2中的代码,可以极大程度上减少工作量,当未扩展App其他功能的时候,Relationship可是以有向图来代存无向图,当扩展关系后,可重写功能实现有向图的操作。DataBase用来储存文件,每一行的数据都被储存在字符串数组中,可以调用接口中的方法来获得这个数据。

对于具体类的系统,我们需要设计他们的系统,但是对于已经写好的系统,我们可以继承它,进行复用,来减少工作量。那么,对于接下来的三个独特的系统,每个都重写或者是增加了一些属于自己的方法

恒星系统StellarSystem:

//产生空星系系统的静态方法:
static <L,E> StellarSystem<L,E> emptySystem(){
    return new ConcreteStellarSystem<>();
}

//获得特定轨道:
@Override
StellarSystemTrack<E> getTrack(E PhysicalObject);
//这是一个重写的方法,返回的类型编程了Track的子类StellarSystemTrack,符合协变的原则

//获得迭代器:
@Override
StellarSystemIterator<E> iterator();
//重写了迭代器的方法,返回的迭代器也是轨道系统迭代器的子类,符合协变原则

//更新某个星体位置:
double getPosition(E PhysicalObject,double time);
//这个方法能获得time秒后星体的角度

//计算距离:
double countDistanceBetweenCentralAndPhysical(E PhysicalObject);
double countDistanceBetweenPhysicals(E Object1,E Object2);
//计算星体间距离的方法

//得到轨道集合:
Set<StellarSystemTrack<E>> getStellarSystemTracks();
//因为集合中轨道的种类变了,但是无法重写方法,所以只能新写一个。

原子系统:

//获得特定轨道:
@Override
AtomicStructureTrack<E> getTrack(E PhysicalObject);

//获得迭代器:
@Override
AtomicStructureIterator<E> iterator();

//获得轨道集合:
Set<AtomicStructureTrack<E>> getAtomStructureTracks();

//迁移轨道:
void transit(E object, AtomicStructureTrack track1, AtomicStructureTrack track2);
//采用了重载的方式,和超类中的transit采用了一个命名方式,但是多了一个输入:迁移前轨道。

人际交往系统:

//获得特定轨道:
@Override
SocialNetworkCircleTrack<E> getTrack(E PhysicalObject);

//关系的设置:
@Override
boolean setGraph(Graph graph);
//因为这里,人际关系圈的关系图和原本系统的关系图要求不一致,所以需要重写这部分方法

//获得迭代器:
@Override
SocialNetworkCircleIterator<E> iterator();

//增加关系:
boolean addRelationshipBetweenCentralAndPhysical(L CentralObject,E PhysicalObject,double weight);
boolean addRelationshipBetweenPhysicals(E PhysicalObject1,E PhysicalObject2,double weight);
//这个方法是知道了具体物体时用的两个方法

//删除关系:
boolean deleteRelationshipBetweenCentralAndPhysical(L CentralObject,E PhysicalObject);
boolean deleteRelationshipBetweenPhysicals(E PhysicalObject1,E PhysicalObject2);

对于三个系统来说,用很多共同的相似之处,也有一些不同的地方,但是他们的rep在初始系统中都有体现,所以并没有额外增加rep来储存其他的数据。

3.4面向复用的设计:Track

不同的系统既有共通之处,也有不同的地方,所以我们有一个原始系统,另外又演变出来三个子类系统,那么对于系统的内部要使用的某个ADT来说,我们也是同样的道理,所以,对于轨道类,我们也设计出一个原始的轨道Track和它的三个子类StellarSystemTrack,AtomicStructureTrack和SocialNetworkCircleTrack,轨道是一个不可变的数据类型,所以我们内部不要有对其更改的方法,rep都用了final的数据类型。

工厂的方法在每一个轨道中都进行了应用,下面只对第一个原始的轨道进行说明,不再一一呈现。

原始轨道:

rep:

private final double radius;
private final Set<E> objects = new HashSet<>();
private final Map<E, Double> angles = new HashMap<>();
private final int num;

radius用来储存轨道半径,objects用来储存轨道上有哪些物体,angles用来储存这些物体的角度,num来记录轨道的编号

方法:

//静态方法:
public static <E> Track<E> createTrack(double radius,int num){
    return OriginTrackFactory.createTrack(radius,num);
}
//添加物体:
boolean add(E object);

//移除物体:
boolean remove(E object);

//设置某个物体的角度:
boolean setAngle(E object,Double angle);

//获得某个物体角度:
double getAngle(E object);

//获得物体集合:
Set<E> getObjects();

//获得角度集合:
Map<E,Double> getAngles();

//获得轨道半径:
double getRadius();

//获得轨道编号:
int getNum();

对于个性化的轨道,我在这里只给出其特有的数据类型和方法,超类中所继承的除非必要,后续将不提及。

StellarSystemTrack:

rep:

private final Map<E,Double> Speed = new HashMap<>();

新增的rep用来储存行星速度,在原本的轨道中,轨道物体是没有定义速度这一概念的,但是行星有着自己的公转速度,而在后续的电子和朋友中,也不会用到速度的概念,这属于恒星系统的独有概念,所以我将其放到了行星轨道中。

方法:

//设置行星速度:
boolean setSpeed(E object,double speed);

//获得行星速度:
double getSpeed(E object);

AtomicStructureTrack:

rep:

private int amount;
private double angle;
private int num = 0;

方法:

//添加物体:
@Override
boolean add(E object);

//移除物体:
@Override
boolean remove(E object);

SocialNetworkCircleTrack:

此轨道相对于原始轨道没有产生变化,只是简单的继承,至于为什么不用初始轨道Track,实际上是为了好区分,方便进行统一的规划。

3.5面向复用的设计

这部分对应的应该是中心物体的ADT定义,这部分物体也是不可变的,所以我们也要注意其不可变性

其实对于这部分ADT的构建,每个接口都有属于自己的静态方法,其调用了静态工厂的方法,隐藏了具体实现的过程,在下面就不一一呈现了。

Stellar:

rep:

private final String name;
private final double radius;
private final double mass;

方法:

@Override
public String getName(){return name;}
@Override
public double getRadius(){return radius;}
@Override
public double getMass(){return mass;}

AtomicNucleus:

rep:

private final String name;

方法:

@Override
public String getName() {return this.name;}

CentralUser:

rep:

private final int age;
private final String name;
private final char sex;

方法:

@Override
public int getAge(){
    return this.age;
}
@Override
public String getName(){
    return this.name;
}
@Override
public char getSex(){
    return this.sex;
}

面向复用的设计:PhysicalObject

这部分的内容是针对轨道物体的一个ADT的构建,这里我采用了一个接口的方式将三个物体进行了统一,也就是三个物体都是这个接口的实现,其中不同的实现还有着额外的方法去观察其内部的数据。其实在我们设计的时候,可以采用不同的接口,那样的设计更加明了。

接口PhysicalObject:

/**
 * 创建行星的静态方法
 * @param name 行星名字
 * @param state 行星状态
 * @param color 行星颜色
 * @return 一颗行星
 */
public static Planet createPlanet(String name,String state,String color,double radius1,double radius2,double speed,String direction,double angle){
    return PlanetFactory.createPlanet(name, state, color, radius1, radius2, speed, direction, angle);

/**
 * 创造电子的静态方法
 * @param num 电子编号
 * @return 一个电子
 */
public static Electron createElectron(int num){
    return ElectronFactory.createElectron(num);
}

/**
 * 创造朋友的静态方法
 * @param name 朋友的名字
 * @param age 朋友的年龄
 * @param sex 朋友的性别
 * @return 一个朋友
 */
public static Friend createFriend(String name, int age, char sex){
    return FriendFactory.createFriend(name,age,sex);
}

 这里面有三个静态方法去产生三个轨道物体,每个轨道物体还有观察器,观察器会在实现类中体现。

Planet:

rep:

private final String name;
private final String state;
private final String color;
private final double radius1;//自身半径
private final double radius2;//公转轨道半径
private final double speed;
private final String direction;
private final double angle;

方法:

public String getState(){
    return this.state;
}
public String getName(){
    return this.name;
}
public String getColor(){
    return this.color;
}
public double getRadius1(){
    return this.radius1;
}
public double getRadius2(){
    return this.radius2;
}
public double getSpeed(){
    return this.speed;
}
public String getDirection(){
    return this.direction;
}
public double getAngle(){
    return this.angle;
}

Electron:

rep:

private final int num;

方法:

public int getNum(){
    return num;
}

Friend:

rep:

private final int age;
private final String name;
private final char sex;

方法:

public int getAge(){
    return this.age;
}
public String getName(){
    return this.name;
}
public char getSex(){
    return this.sex;
}

3.7可复用API设计 

关于可复用API设计,这里写了静态的方法去实现这部分内容,只用写一遍,对于其和其子类可用一个静态方法去实现,因为需要计算的rep在超类中已经存在,不用去特化针对每个系统。

/**
 * 计算系统中的熵值
 * @param c 要计算的系统
 * @return 系统的熵值
 */
public static <L,E> double getObjectDistributionEntropy(CircularOrbit<L,E> c){
    int n = c.getAllTracks().size();
    int sum = 0;
    List<Double> p = new ArrayList<>();
    for(Track<E> track:c.getAllTracks()){
        sum = sum + track.getObjects().size();
    }
    for(Track<E> track:c.getAllTracks()){
        double a = (double) track.getObjects().size()/sum;
        p.add(a);
    }
    double K = 1/Math.log(n);
    double s = 0;
    for (int i = 0; i < p.size(); i++) {
        s = s + p.get(i)*Math.log(p.get(i));
    }
    return -K*s;
}

/**
 * 计算两个轨道物体的逻辑距离
 * @param c 系统
 * @param e1 物体1
 * @param e2 物体2
 * @param <E> 轨道物体
 * @return 两个物体间的逻辑距离(最短相隔多少条边)
 */
public static <L,E> int getLogicalDistance (CircularOrbit<L,E> c, Object e1, Object e2){
    Graph Relationship = c.getGraph();

    if (e1 == e2)
        return 0;

    List<Object> l = new ArrayList<>();
    List<Double> dis = new ArrayList<>();
    Set<Object> flag = new HashSet<>();

    l.add(e1);
    dis.add(0.0);
    flag.add(e2);
    int h = 0, t = 0;
    while (h <= t) {
        Object u = l.get(h);
        Map<Object, Double> targets = Relationship.targets(u);
        for (Object key : targets.keySet())
            if (!flag.contains(key)) {
                ++t;
                flag.add(key);
                l.add(key);
                dis.add(dis.get(h) + 1.0);
                //dis.add(dis.get(h) + targets.get(key));
                if (key == e1) {
                    return dis.get(t).intValue();
                }
            }
        ++h;
    }
    return -1;
}

/**
 * 计算两个物体间的实际距离
 * @param c 系统
 * @param e1 物体1
 * @param e2 物体2
 * @param <E> 轨道物体
 * @return 两个物体间的物理距离
 */
public static <L,E> double getPhysicalDistance (CircularOrbit<L,E> c, E e1, E e2){
    Track<E> t1 = c.getTrack(e1);
    Track<E> t2 = c.getTrack(e2);
    double angle1 = t1.getAngle(e1);
    double angle2 = t2.getAngle(e2);
    double radius1 = t1.getRadius();
    double radius2 = t2.getRadius();
    double distance = radius1*radius1+radius2*radius2-2*radius1*radius2*Math.cos((angle1-angle2)*Math.PI/180.0);
    return Math.sqrt(distance);
}

3.8图的可视化:第三方API的复用

调用了java内部可视化的方法,采用了swing库画图,内部含有画空心圆,画实心圆,画字符串的操作,对于当前效果的可视化已经够用了

//1.定义画板(显式初始化为null)
private final Sketchpad sketchpad;
private CircularOrbit system;

public static void visualize(CircularOrbit c){
    new CircularOrbitHelper(c);
}

public CircularOrbitHelper(CircularOrbit system) {
    this.system = system;
    //2.初始化画板
    sketchpad = new Sketchpad();
    //3.将画板嵌入画框
    this.add(sketchpad);
    //4.设置画板的大小(绘图区域)
    this.setSize(1920, 1080);
    this.setVisible(true);  //true表示可见
    //5.设置点击“x”按钮即可退出程序
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

class Sketchpad extends JPanel {
    private Map<Object,Integer> x = new HashMap<>();
    private Map<Object,Integer> y = new HashMap<>();

    public void paint(Graphics g) {
        super.paint(g); //注意 : 一定要使用带参数的父类的paint方法。

        //画中心物体
        Map<Object,String> nameList = system.getName();
        x.put(system.getCentralObject(),960);
        y.put(system.getCentralObject(),540);
        g.fillOval(960-15,540-15,30,30);
        if(!(nameList.get(system.getCentralObject()) == null))
            g.drawString(nameList.get(system.getCentralObject()),960-15,540-15);

        //画轨道和轨道物体
        Set<Track> tracks = system.getAllTracks();
        int num;
        if(tracks.size()!=0)
            num = (int)400/tracks.size();
        else
            num=0;
        List<Track> list = new ArrayList<>();
        double ttrack = 9*Math.pow(10,50);
        Track t=null;
        for (int i=0;i<tracks.size();i++) {
            for (Track track : tracks) {
                if (track.getRadius() < ttrack && !(list.contains(track))) {
                    t = track;
                    ttrack = track.getRadius();
                }

            }
            list.add(t);
            ttrack = 9 * Math.pow(10, 50);
        }
        int i = 1;
        for(Track track:list){
            g.drawOval(960-i*num,540-i*num,i*num*2,i*num*2);
            g.drawString(String.valueOf(track.getNum()),960-(int)(i*num/Math.sqrt(2)),540-(int)(i*num/Math.sqrt(2)));
            for(Object object:track.getObjects()) {
                x.put(object, 960 + (int) (i * num * Math.cos(track.getAngle(object) * Math.PI / 180.0)));
                y.put(object, 540 - (int) (i * num * Math.sin(track.getAngle(object) * Math.PI / 180.0)));
                g.fillOval(x.get(object) - 10, y.get(object) - 10, 20, 20);
                if (!(nameList.get(object) == null))
                    g.drawString(nameList.get(object), x.get(object) - 10, y.get(object) - 10);
            }
            i++;
        }

        //画物体之间的联系
        Graph graph = system.getGraph();
        for(Object source:graph.vertices()){
                graph.targets(source).forEach((key, value) -> {
                    g.drawLine(x.get(source), y.get(source), x.get(key), y.get(key));
                });
        }

    }
}

可视化完成后,成品如下

StellarSystem:

AtomicStruture:

SocialNetworkCircle:

对于每一个系统,左上角都是轨道编号,而且,为了方便观察,我将轨道特意调制成等宽的,对于行星来说左上角将是轨道的半径,这样能很清晰的得知轨道的大小,等级等等。

3.9设计模式的应用

工厂模式:

在中心物体,轨道物体,轨道的建立都有应用

迭代器模式:

设计了一个由内自外遍历的迭代器 ,这个迭代器的设计模式沿用了java内部的迭代器样子设计的,以最典型的原始轨道迭代器为例

接口:

接口:public interface CircularOrbitIterator<E> extends Iterator {

    /**
     * 判断下面还有没有可以遍历的元素
     * @return 若存在,则返回true
     * 若不存在,则返回false
     */
    boolean hasNext();

    /**
     * 赋值下一个元素
     * @return 下一个元素
     */
    E next();

    /**
     * 移除某个元素
     */
    void remove();

}

对于内部的迭代器获得以及实现:

Override
public CircularOrbitIterator<E> iterator() {
    return new Itr();
}

public class Itr implements CircularOrbitIterator<E> {

    int cursor = 0;       // index of next element to return
    int lastRet = -1; // index of last element returned; -1 if no such
    int size = PhysicalObjects.size();
    List<E> list = new ArrayList<>(sort());

    @Override
    public boolean hasNext() {
        return cursor != size;
    }

    @Override
    public E next() {
        int i = cursor;
        cursor++;
        return this.list.get(lastRet = i);
    }

    public void remove(){
        if (lastRet < 0)
            throw new IllegalStateException();
        ConcreteCircularOrbit.this.removePhysicalObject(this.list.get(lastRet));
        list.remove(lastRet);
        cursor = lastRet;
        this.size = PhysicalObjects.size();
        lastRet = -1;
    }

    /**
     * 获得一个由内至外,角度由小到大的轨道物体排列列表
     * @return 列表
     */
    private List<E> sort(){
        List list =  Arrays.asList(PhysicalObjects.toArray());
        Collections.sort(list, new Comparator<E>() {
            @Override
            public int compare(E e1, E e2) {
                if(getTrack(e1).getRadius() > getTrack(e2).getRadius())
                    return 1;
                else if(getTrack(e1).getRadius() < getTrack(e2).getRadius())
                    return -1;
                else{
                    if(getTrack(e1).getAngle(e1) > getTrack(e2).getAngle(e2))
                        return 1;
                    else if(getTrack(e1).getAngle(e1) < getTrack(e2).getAngle(e2))
                        return -1;
                    else
                        return 0;
                }
            }
        });
        return list;
    }
}

这是一个内部的类,设置成public是因为后续继承方便沿用,也可以设置成locked,只允许子类去继承,重写了compare方法,使得物体的排列比较变成了,优先比较轨道,按轨道有内自外排列,轨道相同的时候,比角度,按角度由小自大排列,然后将这些物体塞到一个固定顺序的列表,一次弹出即可。

3.10应用的设计与开发 

利用上述设计和实现的ADT,实现手册里要求的各项功能。

以下各小节,只需保留和完成你所选定的应用即可。

3.10.2StellarSystem

最后这个StellarSystemApps会调用前面写好的功能组成一个可用的app,在最终的App类中集成成为一个三合一app

3.10.3AtomicStructure

同上

3.10.5SocialNetworkCircle

同上,有些方法没有截图进去:构建系统,可视化。

3.11应对应用面临的新变化

以下各小节,只需保留和完成你所选定的应用即可。

3.11.2StellarSystem

构建新的星系轨道,是原本星系轨道的子类 ,多加一个参数,前一个轨道的半径用来存长轴,新加的用来存短轴。在系统和应用中应用即可

public class ConcreteEllipticalTrack<E> extends ConcreteStellarSystemTrack<E> implements EllipticalTrack<E>{

    private final double radius;

    /**
     * 椭圆轨道类构造器
     * @param radius1 长轴
     * @param radius2 短轴
     * @param num 编号
     */
    public ConcreteEllipticalTrack(double radius1,double radius2,int num){
        super(radius1,num);
        this.radius = radius2;
    }

    @Override
    public double getMajorAxis() {
        return super.getRadius();
    }

    @Override
    public double getMinorAxis() {
        return radius;
    }
}

3.11.3AtomicStructure

构建新的中心物体,多加两个参数去存质子数量和中子数量。在系统和应用中应用即可。

public class ConcreteAtomicNucleus2 extends ConcreteAtomicNucleus implements AtomicNucleus2{

    private final int num1;
    private final int num2;

    public ConcreteAtomicNucleus2(String name,int num1,int num2){
        super(name);
        this.num1=num1;
        this.num2=num2;
    }

    public int getProton(){
        return num1;
    }

    public int getNeutron(){
        return num2;
    }
}

3.11.5SocialNetworkCircle

构建了新的系统,去继承人际关系系统,重写了有关关系的所有方法,新写了个SocialNetworkCircle2,因为关于关系的录入需要变化

@Override
public boolean setRelationship(Object object1,Object object2,double num){
    if(object1 == super.getCentralObject()&&super.getPhysicalObjects().contains(object2)){
        super.setRelationship(object1, object2, num);
        return true;
    }
    else if(object2 == super.getCentralObject()&&super.getPhysicalObjects().contains(object1)){
        return false;
    }
    else if(super.getPhysicalObjects().contains(object2)&&super.getPhysicalObjects().contains(object1)){
        if(super.getTrack((E) object1).getNum()>super.getTrack((E) object2).getNum())
            return false;
        super.setRelationship(object1, object2, num);
        return true;
    }
    else
        return false;
}

@Override
public boolean addRelationshipBetweenCentralAndPhysical(L CentralObject,E PhysicalObject,double weight){
    Graph Relationship = super.getGraph();
    //中心物体不存在,或者轨道物体不存在
    if(CentralObject==null||!super.getPhysicalObjects().contains(PhysicalObject))
        return false;
        //中心物体和轨道物体存在关系
    else if(Relationship.targets(CentralObject).containsKey(PhysicalObject))
        return false;
        //否则
    else {
        Relationship.set(CentralObject, PhysicalObject, weight);
        super.setGraph(Relationship);
        return true;
    }
}

@Override
public boolean addRelationshipBetweenPhysicals(E PhysicalObject1,E PhysicalObject2,double weight){
    Graph Relationship = super.getGraph();
    //物体1或者物体2不存在,则返回false
    if(!super.getPhysicalObjects().contains(PhysicalObject1)||!super.getPhysicalObjects().contains(PhysicalObject2))
        return false;
        //物体1与物体2之间存在关系
    else if(Relationship.targets(PhysicalObject1).containsKey(PhysicalObject2))
        return false;
        //否则
    else {
        if(super.getTrack(PhysicalObject1).getNum()>super.getTrack(PhysicalObject2).getNum())
            return false;
        Relationship.set(PhysicalObject1, PhysicalObject2, weight);
        super.setGraph(Relationship);
        return true;
    }
}

@Override
public boolean deleteRelationshipBetweenCentralAndPhysical(L CentralObject, E PhysicalObject) {
    Graph Relationship = super.getGraph();
    //中心物体不存在,或者轨道物体不存在
    if(CentralObject==null||!super.getPhysicalObjects().contains(PhysicalObject))
        return false;
        //中心物体和轨道物体不存在关系
    else if(!Relationship.targets(CentralObject).containsKey(PhysicalObject))
        return false;
        //否则
    else {
        Relationship.set(CentralObject, PhysicalObject, 0);
        super.setGraph(Relationship);
        return true;
    }
}

@Override
public boolean deleteRelationshipBetweenPhysicals(E PhysicalObject1, E PhysicalObject2) {
    Graph Relationship = super.getGraph();
    //物体1或者物体2不存在,则返回false
    if(!super.getPhysicalObjects().contains(PhysicalObject1)||!super.getPhysicalObjects().contains(PhysicalObject2))
        return false;
        //物体1与物体2之间不存在关系
    else if(!Relationship.targets(PhysicalObject1).containsKey(PhysicalObject2))
        return false;
        //否则
    else {
        Relationship.set(PhysicalObject1, PhysicalObject2, 0);
        super.setGraph(Relationship);
        return true;
    }
}

 3.12Git仓库结构

 由于实验报告需要最后制作,所以master和change分支都还有一次额外的提交

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值