Anhui University software construction experiment set

Posted by dhruvasagar on Mon, 31 Jan 2022 04:31:39 +0100

Experiment 1: engineering method and abstract factory pattern

Experimental topic

The process of producing clothes in a garment factory is simulated by using the factory method and abstract factory mode. The specific contents are as follows:

There are three kinds of jackets of brands A, B and C, which use simple factory mode and factory method mode to realize the code of producing jackets of various brands (that is, print sentences such as "producing jackets of brand A")

A. In addition to producing jackets, brands B and C can also reproduce pants, and use the abstract factory mode to realize the production process of jackets and pants of various brands.

directory structure

D:.
└─com
    └─longstudy
        ├─abstractfactory
        │  ├─factory
        │  │  │  AbstractFactory.java
        │  │  │
        │  │  └─impl
        │  │          AFactory.java
        │  │          BFactory.java
        │  │          CFactory.java
        │  │
        │  ├─jacket
        │  │  │  Jacket.java
        │  │  │
        │  │  └─impl
        │  │          JacketA.java
        │  │          JacketB.java
        │  │          JacketC.java
        │  │
        │  └─trouser
        │      │  Trouser.java
        │      │
        │      └─impl
        │              TrouserA.java
        │              TrouserB.java
        │              TrouserC.java
        │
        ├─factory
        │  │  JacketFactory.java
        │  │
        │  └─jacket
        │      │  Jacket.java
        │      │
        │      └─impl
        │              JacketA.java
        │              JacketB.java
        │              JacketC.java
        │
        └─factorymethod
            ├─factory
            │  │  JFactory.java
            │  │
            │  └─impl
            │          JacketAFractory.java
            │          JacketBFractory.java
            │          JacketCFractory.java
            │
            └─jacket
                │  Jacket.java
                │
                └─impl
                        JacketA.java
                        JacketB.java
                        JacketC.java

Experimental code

Simple factory

public interface Jacket {
    void printJacket();
}
public class JacketA implements Jacket {
    @Override
    public void printJacket() {
        System.out.println("Production jacket A");
    }
}
public class JacketB implements Jacket {
    @Override
    public void printJacket() {
        System.out.println("Production jacket B");
    }
}
public class JacketC implements Jacket {
    @Override
    public void printJacket() {
        System.out.println("Production jacket C");
    }
}
public class JacketFactory {
    public Jacket getJacket(String jacket){
        if(jacket==null){
            return null;
        }
        if (jacket.equals("A")){
            return new JacketA();
        }else if(jacket.equals("B")){
            return new JacketB();
        }else if(jacket.equals("C")){
            return new JacketC();
        }
        return null;
	}
}

Test:

public class JacketFactory {
    public Jacket getJacket(String jacket){
        if(jacket==null){
            return null;
        }
        if (jacket.equals("A")){
            return new JacketA();
        }else if(jacket.equals("B")){
            return new JacketB();
        }else if(jacket.equals("C")){
            return new JacketC();
        }
        return null;
    }
}

Factory method

public interface JFactory {
    Jacket createJacket();
}
public class JacketAFractory implements JFactory {
    @Override
    public Jacket createJacket() {
        return new JacketA();
    }
}
public class JacketBFractory implements JFactory {
    @Override
    public Jacket createJacket() {
        return new JacketB();
    }
}
public class JacketCFractory implements JFactory {
    @Override
    public Jacket createJacket() {
        return new JacketC();
    }
}

Test:

public class MyTest2 {
    @Test
    public void factoryMethodTest(){
        JFactory afactoty = new JacketAFractory();
        Jacket a = afactoty.createJacket();
        System.out.println(a.getClass());
        a.printJacket();

        JFactory bfactoty = new JacketBFractory();
        Jacket b = bfactoty.createJacket();
        System.out.println(b.getClass());
        b.printJacket();

        JFactory cfactoty = new JacketCFractory();
        Jacket c = cfactoty.createJacket();
        System.out.println(c.getClass());
        c.printJacket();
    }
}

Abstract factory

public abstract class AbstractFactory {
    public abstract Jacket getJacket();
    public abstract Trouser getTrouser();
}
public class AFactory extends AbstractFactory {
    @Override
    public Jacket getJacket() {
        return new JacketA();
    }

    @Override
    public Trouser getTrouser() {
        return new TrouserA();
    }
}
public class BFactory extends AbstractFactory {
    @Override
    public Jacket getJacket() {
        return new JacketB();
    }

    @Override
    public Trouser getTrouser() {
        return new TrouserB();
    }
}
public class CFactory extends AbstractFactory {
    @Override
    public Jacket getJacket() {
        return new JacketC();
    }

    @Override
    public Trouser getTrouser() {
        return new TrouserC();
    }
}

Test:

public class MyTest3 {
    @Test
    public void abstractFactoryTest(){
        try{
            AbstractFactory afactory = new AFactory();
            afactory.getJacket().printJacket();
            afactory.getTrouser().trouserPrint();
            AbstractFactory bfactory = new BFactory();
            bfactory.getJacket().printJacket();
            bfactory.getTrouser().trouserPrint();
            AbstractFactory cfactory = new CFactory();
            cfactory.getJacket().printJacket();
            cfactory.getTrouser().trouserPrint();
        }catch (NullPointerException e){
            e.printStackTrace();
        }
    }
}

Experiment 2: programming implementation of generator mode and prototype mode

Experimental topic

The production of IBM computer is simulated by using the producer mode. The main structure of IBM computer is expressed as follows:

class IBM{
	string monitor = "IBM Display of";
    string keyboard = "IBM Keyboard for";
    string mouse = "IBM Mouse";
    Motherboard* MB;
    void display();
}

MB is a main board, and its main connections are as follows:

class Motherboard{
    string CPU;
    string RAM;
}

That is, the motherboard contains CPU and RAM. display is a function for printing various components, which is mainly used to check whether the production is correct.

The construction sequence is to produce the main board first, and then the display, keyboard and mouse.

After the first IBM computer is produced in the producer mode, the prototype mode is used to assign another two to the computer.

directory structure

│  Director.java
│  IBMProduct.java
│  Main.java
│  Motherboard.java
└─builder
        Builder.java
        ConcreteBuilderPlan.java

Experimental code

Motherboard class:

public class Motherboard {
    private String CPU;
    private String RAM;

    public Motherboard() {
    }

    public Motherboard(String CPU, String RAM) {
        this.CPU = CPU;
        this.RAM = RAM;
    }

    @Override
    public String toString() {
        return "Motherboard{" + CPU + "," + RAM  + '}';
    }

    public Motherboard clone(){
        Motherboard motherboard = new Motherboard();
        motherboard.setCPU(this.CPU);
        motherboard.setRAM(this.RAM);
        return motherboard;
    }

    public String getCPU() {
        return CPU;
    }

    public void setCPU(String CPU) {
        this.CPU = CPU;
    }

    public String getRAM() {
        return RAM;
    }

    public void setRAM(String RAM) {
        this.RAM = RAM;
    }
}

IBMProduct:

public class IBMProduct {
    private String monitor;
    private String keyboard;
    private String mouse;
    private Motherboard MB;

    public IBMProduct() {
    }

    public IBMProduct clone(){
        IBMProduct ibmProduct = new IBMProduct();
        ibmProduct.setKeyboard(this.keyboard);
        ibmProduct.setMonitor(this.monitor);
        ibmProduct.setMouse(this.mouse);
        Motherboard mb = MB.clone();
        ibmProduct.setMB(mb);
        return ibmProduct;
    }

    public void show() {
        System.out.println("IBM product:");
        System.out.println(this.MB.getCPU()+","+this.MB.getRAM());
        System.out.println(this.monitor);
        System.out.println(this.keyboard);
        System.out.println(this.mouse);
    }

    public void setMonitor(String monitor) {
        this.monitor = monitor;
    }

    public void setKeyboard(String keyboard) {
        this.keyboard = keyboard;
    }

    public void setMouse(String mouse) {
        this.mouse = mouse;
    }

    public void setMB(Motherboard MB) {
        this.MB = MB;
    }
}

Builder interface:

public interface Builder {
    void BuildMonitor();
    void BuildKeyboard();
    void BuildMouse();
    void BuildMotherBoard();
    default IBMProduct getResult(){
        return null;
    }
}

Implementation class of Builder interface:

public class ConcreteBuilderPlan implements Builder {
    private IBMProduct product = new IBMProduct();

    @Override
    public void BuildMonitor() {
        product.setMonitor("IBM----monitor");
    }

    @Override
    public void BuildKeyboard() {
        product.setKeyboard("IBM----monitor");
    }

    @Override
    public void BuildMouse() {
        product.setMouse("IBM----mouse");
    }

    @Override
    public void BuildMotherBoard() {
        Motherboard motherboard = new Motherboard();
        motherboard.setCPU("IBM----CPU");
        motherboard.setRAM("IBM----RAM");
        product.setMB(motherboard);
    }

    @Override
    public IBMProduct getResult() {
        return product;
    }
}

Commander category:

public class Director {
    public void construct(Builder builder){
        builder.BuildMotherBoard();
        builder.BuildMonitor();
        builder.BuildKeyboard();
        builder.BuildMouse();
    }
}

Test:

public class Main {
    public static void main(String[] args) {
        Director director = new Director();
        ConcreteBuilderPlan concreteBuilderPlan = new ConcreteBuilderPlan();
        director.construct(concreteBuilderPlan);
        IBMProduct result = concreteBuilderPlan.getResult();
        result.show();

        System.out.println("*************Prototype mode***************");

        IBMProduct clone = result.clone();
        clone.setMouse("HP----mouse");
        clone.setKeyboard("ASUS----keyboard");
        clone.setMouse("HP----mouse");
        clone.setMB(new Motherboard("Intel----CPU","AMD----RAM"));
        clone.show();

        System.out.println("*************Prototype mode 2***************");

        IBMProduct clone2 = result.clone();
        clone2.setMouse("AMD----mouse");
        clone2.setKeyboard("AMD----keyboard");
        clone2.setMonitor("AMD----keyboard");
        clone2.setMouse("AMD----mouse");
        clone2.setMB(new Motherboard("AMD----CPU","AMD----RAM"));
        clone2.show();
    }
}

Experiment 3: programming implementation of decoration mode

Experimental topic

Use the factory method pattern to instantiate two car classes, such as Toyota and Volvo.

For these two initial cars (Toyota and Volvo), new functions are added to them respectively by using decoration mode, in which Toyota can navigate and drive automatically, and Volvo can navigate and voice control.

directory structure

G:.
│  Client.java
├─car
│      Car.java
│      Toyota.java
│      Volvo.java
├─decorator
│      NewToyota.java
│      NewVolvo.java
│      ToyotaDecorator.java
│      VolvoDecorator.java
└─factory
        CarFactory.java
        ToyotaFactory.java
        VolvoFactory.java

Implementation code

example:

public interface Car {
    void printCar();
}
public class Toyota implements Car {
    @Override
    public void printCar() {
        System.out.println("This is a car Toyota");
    }
}
public class Volvo implements Car {
    @Override
    public void printCar() {
        System.out.println("This is a car Volvo");
    }
}

Factory:

public interface CarFactory {
    Car createCar();
}
public class ToyotaFactory implements CarFactory {
    @Override
    public Toyota createCar() {
        return new Toyota();
    }
}
public class VolvoFactory implements CarFactory{
    @Override
    public Volvo createCar() {
        return new Volvo();
    }
}

Decorator:

public interface NewToyota extends Car {
    // Navigation
    void navigation();
    // Automatic driving
    void autopilot();
}
public interface NewVolvo extends Car {
    // Navigation
    void navigation();
    // Voice control
    void voiceControl();
}
public class ToyotaDecorator implements NewToyota {
    private final Car car;

    public ToyotaDecorator(Car car) {
        this.car = car;
    }

    @Override
    public void navigation() {
        System.out.println("Add function---Navigation");
    }

    @Override
    public void autopilot() {
        System.out.println("Add function---Automatic driving");
    }

    @Override
    public void printCar() {
        car.printCar();
    }
}
public class VolvoDecorator implements NewVolvo {
    private final Car car;

    public VolvoDecorator(Car car) {
        this.car = car;
    }

    @Override
    public void navigation() {
        System.out.println("Add function---Navigation");
    }

    @Override
    public void voiceControl() {
        System.out.println("Add function---Voice control");
    }

    @Override
    public void printCar() {
        car.printCar();
    }
}

Client call:

public class Client {
    public static void main(String[] args) {
        /**
         * Toyota
         */
        // Factory production
        ToyotaFactory toyotaFactory = new ToyotaFactory();
        Toyota toyota = toyotaFactory.createCar();
        // decorate
        ToyotaDecorator toyotaDecorator = new ToyotaDecorator(toyota);
        toyotaDecorator.printCar();
        toyotaDecorator.autopilot();
        toyotaDecorator.navigation();
        /**
         * Volvo
         */
        VolvoFactory volvoFactory = new VolvoFactory();
        Volvo volvo = volvoFactory.createCar();

        VolvoDecorator volvoDecorator = new VolvoDecorator(volvo);
        volvoDecorator.printCar();
        volvoDecorator.navigation();
        volvoDecorator.voiceControl();
    }
}

Experiment 4: combination mode and responsibility chain mode

Experimental topic

According to the figure below, the structure of the company is constructed by using the combination mode.

That is, the head office has Shanghai East China branch, and the East China branch has Nanjing Office and Hangzhou office. Among them, branches at all levels have human resources department and finance department.

After using the combination mode to build the structure, the responsibility chain mode is used to process the salary increase requests of employees everywhere.

For example, an employee in Nanjing asks for a raise. If the raise does not exceed 1000 yuan, the Nanjing office can approve it; If it exceeds 1000 yuan, it shall be reported to East China branch; if it is less than 2000 yuan, it shall be approved; If it exceeds, it shall be reported to Beijing head office. If it does not exceed 3000 yuan, it shall be approved by the head office, otherwise it shall be rejected.

Experimental code

public interface Component {
    void add(Component c);
    void remove(Component c);
    void print(int depth);
    void handlerRequest(int request);
}
public class Department implements Component{
    private String name;
    // Minimum wage and maximum wage range
    private int low;
    private int high;
    private Component successor;
    private List<Component> departmentsList = new LinkedList<>();

    public Department() { }

    public Department(String name) {
        this.name = name;
    }

    // Set salary upper and lower limits
    public void setBound(int low,int high){
        this.low=low;
        this.high=high;
    }

    public void setSuccessor(Component c){
        this.successor=c;
    }

    @Override
    public void add(Component c) {
        this.departmentsList.add(c);
    }

    @Override
    public void remove(Component c) {
        this.departmentsList.remove(c);
    }

    // Recursively print the constructed tree
    public void print(int depth){
        for(int i=1;i<=depth;i++){
            System.out.print("--");
        }
        System.out.println(this.name);
        for (Component department : departmentsList) {
            department.print(depth+1);
        }
    }

    @Override
    public void handlerRequest(int request) {
        if(request>=low && request<=high){
            System.out.println(this.name+">>>Processing requests,Raise salary:"+request);
        }else if(successor!=null){
            System.out.println(this.name+">>>No permission");
            successor.handlerRequest(request);
        }else{
            System.out.println(this.name+">>>Just don't give you a raise");
        }
    }
}

Client test:

public class Client {
    public static void main(String[] args) {
        Department node1 = new Department("Beijing company headquarters");
        Department node2 = new Department("Human Resources Department");
        Department node3 = new Department("Shanghai East China branch");
        Department node4 = new Department("Finance Department");
        Department node5 = new Department("Nanjing Office");
        Department node6 = new Department("Hangzhou Office ");
        // Build tree
        node1.add(node2);
        node1.add(node3);
        node1.add(node4);
        node3.add(node5);
        node3.add(node2);
        node3.add(node4);
        node3.add(node6);
        node5.add(node2);
        node5.add(node4);
        node6.add(node2);
        node6.add(node4);
        node1.print(0);
        // Building responsibility chain
        node5.setSuccessor(node3);
        node6.setSuccessor(node3);
        node3.setSuccessor(node1);
        // Set salary increase boundary
        node5.setBound(0,1000);
        node6.setBound(0,1000);
        node3.setBound(1000,2000);
        node1.setBound(2000,3000);
        // Ask for a raise
        System.out.println("**********************");
        node5.handlerRequest(500);
        System.out.println("**********************");
        node5.handlerRequest(1500);
        System.out.println("**********************");
        node5.handlerRequest(2500);
        System.out.println("**********************");
        node5.handlerRequest(3500);
    }
}

Experiment 5: interpreter mode

Experimental topic

Using the interpreter mode, print and calculate the four operations of floating-point numbers

For example: 3 + (4 * 6 - (7 / 2)) = 23.5

directory structure

G:.
│  Client.java
└─expression
    │  Context.java
    │  Expression.java
    │  Variable.java
    └─impl
            AddExpression.java
            Bracket.java
            DivExpression.java
            MulExpression.java
            SubExpression.java

Experimental code

Declare abstract classes:

public abstract class Expression {
    /**
     * analysis
     * @param con Variable object - number
     * @return number
     */
    public abstract double interpreter(Context con);

    /**
     * Print
     * @param con Variable object - number
     */
    public abstract void display(Context con);
}

Variable encapsulation:

public class Variable extends Expression {
    @Override
    public double interpreter(Context con) {
        return con.LookupValue(this);
    }

    @Override
    public void display(Context con) {
        System.out.print(con.LookupValue(this));
    }
}
public class Context {
    private Map<Variable,Double> valueMap = new HashMap<>();

    /**
     * Store variables in HashMap for subsequent operations
     * @param x Variable object
     * @param y number
     */
    public void addValue(Variable x,double y){
        valueMap.put(x, y);
    }

    /**
     * Get the mapped number corresponding to variable x
     * @param x Variable object
     * @return Get the number of
     */
    public double LookupValue(Variable x){
        return valueMap.get(x);
    }
}

Add, subtract, multiply and divide parentheses:

public class AddExpression extends Expression{
    private Expression left;
    private Expression right;

    public AddExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    /**
     * The variable object is parsed into numbers for operation
     * @param con Variable object - number
     * @return
     */
    @Override
    public double interpreter(Context con) {
        return left.interpreter(con)+right.interpreter(con);
    }

    @Override
    public void display(Context con) {
        left.display(con);
        System.out.print("+");
        right.display(con);
    }
}
public class SubExpression extends Expression{
    private Expression left;
    private Expression right;

    public SubExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public double interpreter(Context con) {
        return left.interpreter(con)-right.interpreter(con);
    }

    @Override
    public void display(Context con) {
        left.display(con);
        System.out.print("-");
        right.display(con);
    }
}
public class MulExpression extends Expression {
    private Expression left;
    private Expression right;

    public MulExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public double interpreter(Context con) {
        return left.interpreter(con)*right.interpreter(con);
    }

    @Override
    public void display(Context con) {
        left.display(con);
        System.out.print("*");
        right.display(con);
    }
}
public class DivExpression extends Expression {
    private Expression left;
    private Expression right;

    public DivExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public double interpreter(Context con) {
        return (1.0*left.interpreter(con))/right.interpreter(con);
    }

    @Override
    public void display(Context con) {
        left.display(con);
        System.out.print("/");
        right.display(con);
    }
}
/**
 * Bracket parsing
 * @author Jonny Long
 * @date 2021/6/17 9:15
 */
public class Bracket extends Expression {
    private Expression exp;

    public Bracket(Expression exp) {
        this.exp = exp;
    }

    @Override
    public double interpreter(Context con) {
        return exp.interpreter(con);
    }

    @Override
    public void display(Context con) {
        System.out.print("(");
        exp.display(con);
        System.out.print(")");
    }
}

Client test:

public class Client {
    public static void main(String[] args) {
        Expression exp;
        Context con = new Context();
        Variable a = new Variable();
        Variable b = new Variable();
        Variable c = new Variable();
        Variable d = new Variable();
        Variable e = new Variable();
        con.addValue(a,3);
        con.addValue(b,4);
        con.addValue(c,6);
        con.addValue(d,7);
        con.addValue(e,2);
        exp = new AddExpression(a,new Bracket(new SubExpression(new MulExpression(b,c),new DivExpression(d,e))));
        exp.display(con);
        System.out.print("="+exp.interpreter(con));
    }
}

Big homework

one

subject

The process of producing clothes in a garment factory is simulated by comprehensively using abstract factory mode and single piece mode. The specific contents are as follows:

There are two kinds of clothing brand factories A and B. the factories of brand A and brand B can produce jackets and trousers. The abstract factory mode is used to realize the code of producing jackets and trousers of various brands (that is, printing sentences such as "producing brand A jacket"), and the single piece mode is used to realize the factories of brand A and brand B as single pieces.

Try to complete the following work:

(1) Draw UML class diagram

(2) The core implementation code is given

Project directory structure

G:.
│  Client.java
├─bean
│  │  Jacket.java
│  │  Trouser.java
│  │
│  ├─jacket
│  │      JacketA.java
│  │      JacketB.java
│  └─trouser
│          TrouserA.java
│          TrouserB.java
└─factory
    │  AbstractFactory.java
    └─impl
            AFactory.java
            BFactory.java

Implementation code

Jacket and coat interface and implementation class:

public interface Jacket {
    void printJacket();
}
public interface Trouser {
    void printTrouser();
}
public class JacketA implements Jacket {
    @Override
    public void printJacket() {
        System.out.println("production A Brand jacket");
    }
}
public class JacketB implements Jacket {
    @Override
    public void printJacket() {
        System.out.println("production B Brand jacket");
    }
}
public class TrouserA implements Trouser {
    @Override
    public void printTrouser() {
        System.out.println("production A Brand coat");
    }
}
public class TrouserB implements Trouser {
    @Override
    public void printTrouser() {
        System.out.println("production B Brand coat");
    }
}

Define factory:

public abstract class AbstractFactory {
    public abstract Jacket getJacket();
    public abstract Trouser getTrouser();
}
public class AFactory extends AbstractFactory {
    private static AFactory instanceA = new AFactory();

    public static AFactory getInstanceA(){
        return instanceA;
    }

    @Override
    public Jacket getJacket() {
        return new JacketA();
    }

    @Override
    public Trouser getTrouser() {
        return new TrouserA();
    }
}
public class BFactory extends AbstractFactory {
    private static BFactory instanceB = new BFactory();

    public static BFactory getInstanceB(){
        return instanceB;
    }

    @Override
    public Jacket getJacket() {
        return new JacketB();
    }

    @Override
    public Trouser getTrouser() {
        return new TrouserB();
    }
}

Client test:

public class Client {
    public static void main(String[] args) {
        AFactory instanceA = AFactory.getInstanceA();
        instanceA.getJacket().printJacket();
        instanceA.getTrouser().printTrouser();

        BFactory instanceB = BFactory.getInstanceB();
        instanceB.getJacket().printJacket();
        instanceB.getTrouser().printTrouser();
    }
}

UML diagram

two

subject

Using the interpreter mode, the printing and operation of algebraic expressions containing only addition and subtraction and parentheses are realized. When assigning a value to c + 3, for example, when assigning a value to c + 3, b + 4:

a+b-(c+3)
=3+4-(5+3)
=-1

The variable name can only be 'a', 'b', 'z', and all variable assignments and constants are integers between 0 and 9. The first line in the output result prints the original expression, a+b-(c+3), that is, it contains the variable name; The second line replaces the variable with the assigned value, i.e. 3 + 4 - (5 + 3); The third line prints the calculation results.

Try to complete the following work:

(1) Give a grammatical expression

(2) Draw UML class diagram

(3) The core implementation code is given

Project directory structure

G:.
│  Client.java
│  Context.java
│  Expression.java
│  Variable.java
└─impl
        AddExpression.java
        Bracket.java
        SubExpression.java

Implementation code

Interface and variable classes:

public abstract class Expression {
    public abstract double interpreter(Context con);
    public abstract void display(Context con);
}
public class Context {
    private Map<Variable,Double> valueMap = new HashMap<>();
    public void addValue(Variable x,double y){
        valueMap.put(x,y);
    }
    public double lookupValue(Variable x){
        return valueMap.get(x);
    }
}
public class Variable extends Expression {
    @Override
    public double interpreter(Context con) {
        return con.lookupValue(this);
    }
    @Override
    public void display(Context con) {
        System.out.print(con.lookupValue(this));
    }
}

Implemented operations:

public class AddExpression extends Expression {
    private Expression left;
    private Expression right;

    public AddExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public double interpreter(Context con) {
        return left.interpreter(con)+right.interpreter(con);
    }

    @Override
    public void display(Context con) {
        left.display(con);
        System.out.print("+");
        right.display(con);
    }
}
public class SubExpression extends Expression {
    private Expression left;
    private Expression right;

    public SubExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public double interpreter(Context con) {
        return left.interpreter(con)-right.interpreter(con);
    }

    @Override
    public void display(Context con) {
        left.display(con);
        System.out.print("-");
        right.display(con);
    }
}
public class Bracket extends Expression {
    private Expression exp;

    public Bracket(Expression exp) {
        this.exp = exp;
    }

    @Override
    public double interpreter(Context con) {
        return exp.interpreter(con);
    }

    @Override
    public void display(Context con) {
        System.out.print("(");
        exp.display(con);
        System.out.print(")");
    }
}

Client test:

public class Client {
    public static void main(String[] args) {
        Expression exp;
        Context con = new Context();
        Variable a = new Variable();
        Variable b = new Variable();
        Variable c = new Variable();
        con.addValue(a,3);
        con.addValue(b,4);
        con.addValue(c,5);
        Variable d = new Variable();
        con.addValue(d,3);
        exp = new SubExpression(new AddExpression(a,b),new Bracket(new AddExpression(c,d)));
        System.out.print("a+b-(c+3)\n=");
        exp.display(con);
        System.out.println("\n="+exp.interpreter(con));
    }
}

UML diagram

three

subject

Using observer mode and mediator mode, a function calculator of binary function is realized. The calculator contains two data classes:

class A{
    int x;
}
class B{
    int y;
}

Store integer variables X and Y respectively. Three function calculator classes need to be implemented to calculate f1(x,y)=x+y, f2(x,y)=x-y and f3(x)=2x respectively.

requirement:

(1) When and only when both classes A and B issue notifications, the three function calculators calculate three new values accordingly.

(2) Class A and class B are decoupled from the three function calculator classes as much as possible.

(3) Function calculators can be added and reduced dynamically.

Try to complete the following work:

(1) Draw UML class diagram

(2) The code is realized by modifying class A and class B and adding appropriate classes

Project directory structure

G:.
│  Client.java
├─data
│      A.java
│      AbstractData.java
│      B.java
├─mediator
│      AbstractMediator.java
│      ConcreteMediator.java
└─observer
        F1.java
        F2.java
        F3.java
        Observer.java

Implementation code

Data class:

public abstract class AbstractData {
    protected AbstractMediator abstractMediator;
    public int num;

    public AbstractData(AbstractMediator abstractMediator) {
        this.abstractMediator = abstractMediator;
    }

    public abstract void send(int num);
}
public class A extends AbstractData {
    public A(AbstractMediator abstractMediator) {
        super(abstractMediator);
    }

    @Override
    public void send(int num) {
        abstractMediator.send(num,this);
    }
}
public class B extends AbstractData {
    public B(AbstractMediator abstractMediator) {
        super(abstractMediator);
    }

    @Override
    public void send(int num) {
        abstractMediator.send(num,this);
    }
}

Intermediary + observed:

This mediator class has two kinds of intelligence:

  • As an intermediary
  • As the object of observation
public abstract class AbstractMediator {
    // Interface as mediator
    public abstract void send(int num, AbstractData abstractData);

    // Observed
    private List<Observer> observerList = new LinkedList<>();

    public void attach(Observer observer){
        observerList.add(observer);
    }
    public void detach(Observer observer){
        observerList.remove(observer);
    }
    public void notifyObserver(){
        for (Observer o:observerList) {
            o.update();
        }
    }
}
public class ConcreteMediator extends AbstractMediator {
    private A a;
    private B b;

    @Override
    public void send(int num, AbstractData abstractData) {
        if (a == abstractData) {
            a.num = num;
        } else if (b == abstractData) {
            b.num = num;
        }
    }

    public void setA(A a) {
        this.a = a;
    }

    public void setB(B b) {
        this.b = b;
    }

    public A getA() {
        return a;
    }

    public B getB() {
        return b;
    }
}

Observer class:

public interface Observer {
    void update();
}
public class F1 implements Observer{
    private int result;
    private ConcreteMediator concreteMediator;

    public F1(ConcreteMediator concreteMediator) {
        this.concreteMediator = concreteMediator;
    }

    @Override
    public void update() {
        result = concreteMediator.getA().num+concreteMediator.getB().num;
        showResult();
    }

    public void showResult() {
        System.out.println("function f1(x,y)=x+y Calculation results="+result);
    }
}
public class F2 implements Observer {
    private int result;
    private ConcreteMediator concreteMediator;

    public F2(ConcreteMediator concreteMediator) {
        this.concreteMediator = concreteMediator;
    }
    @Override
    public void update() {
        result = concreteMediator.getA().num-concreteMediator.getB().num;
        showResult();
    }

    public void showResult() {
        System.out.println("function f2(x,y)=x-y Calculation results="+result);
    }
}
public class F3 implements Observer {
    private int result;
    private ConcreteMediator concreteMediator;

    public F3(ConcreteMediator concreteMediator) {
        this.concreteMediator = concreteMediator;
    }

    @Override
    public void update() {
        result = concreteMediator.getA().num*2;
        showResult();
    }

    public void showResult() {
        System.out.println("function f3(x)=2x Calculation results="+result);
    }
}
public class Client {
    public static void main(String[] args) {
        // Mediator is both a mediator and an observed object
        ConcreteMediator mediator = new ConcreteMediator();
        A a = new A(mediator);
        B b = new B(mediator);
        mediator.setA(a);
        mediator.setB(b);
        a.send(20);
        b.send(5);

        mediator.attach(new F1(mediator));
        mediator.attach(new F2(mediator));
        mediator.attach(new F3(mediator));
        mediator.notifyObserver();
        // Let object a post a new notification
        System.out.println("************New notice*************");
        a.send(-100);
        mediator.notifyObserver();
    }
}

UML diagram

Topics: Java Design Pattern