• 访问者模式
  • 简单工厂模式
  • 工厂方法模式
  • 桥接模式
  • 状态模式

两种适配器模式

中介者模式

策略模式

访问者模式(行为型)图书管理系统中,需要处理每一个书库中资料的页数和作者等信息。书库中的资料包括图书、期刊和论文,其中有些论文是独立存在的,有些论文作为期刊的一部分。使用访问者模式设计该系统,类图如下所示:

clip_image002.jpg

在上图中,ItemHandler是抽象访问者,声明了访问不同类型元素的方法,PageHandler和AuthorHandler作为具体访问者,分别用于对页数和作者信息进行处理;Item是抽象元素类,其子类Book表示图书、Magazine表示期刊、Paper表示论文;Library充当对象结构,用于存储图书、期刊和论文等资料信息。

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Test {
    // 抽象访问者
    public abstract class ItemHandler {
        public abstract void handle(Book item);

        public abstract void handle(Magazine item);

        public abstract void handle(Paper item);
    }

    //
    public interface Item {
        public void accept(ItemHandler handler);
    }

    // 具体访问者
    public class PageHandler extends ItemHandler {
        public void handle(Book item) {
            System.out.println("-------------------");
            // 图书页数处理
            System.out.println("图书: 《" + item.bookName + "》页数:" + item.totalPages);
        }

        public void handle(Magazine item) {
            System.out.println("-------------------");
            // 期刊页数处理
            int pages = 0;
            for (Object obj : item.papers) {
                pages += ((Paper) obj).pages;
            }
            System.out.println("杂志: 《" + item.magazineName + item.magazineNo + "》页数:" + pages);
            System.out.println("  包含论文如下:");
            if (item.papers.size() == 0) {
                System.out.println("    无");
            } else {
                for (Object obj : item.papers) {
                    System.out.println("    论文: 《" + ((Paper) obj).paperTitle + "》页数:" + ((Paper) obj).pages);
                }
            }
        }

        public void handle(Paper item) {
            System.out.println("-------------------");
            // 论文页数处理
            System.out.println("论文: 《" + item.paperTitle + "》页数:" + item.pages);
        }
    }

    // 具体访问者
    public class AuthorHandler extends ItemHandler {
        public void handle(Book item) {
            System.out.println("-------------------");
            // 图书作者处理
            System.out.println("作者: " + item.authorName + " 代表作: 《" + item.bookName + "》");
        }

        public void handle(Magazine item) {
            System.out.println("-------------------");
            // 期刊作者处理
            // 论文作者处理
            if (item.papers.size() == 0) {
                System.out.println("    无");
            } else {
                for (Object obj : item.papers) {
                    System.out.println("作者: " + ((Paper) obj).author + " 著作:《" + ((Paper) obj).paperTitle + "》," + "刊号:"
                            + item.magazineNo);
                }
            }

        }

        public void handle(Paper item) {
            System.out.println("-------------------");
            // 论文作者处理
            System.out.println("作者: " + item.author + " 著作: 《" + item.paperTitle + "》");
            // 期刊论文作者处理

        }
    }

    public class Book implements Item {
        public String bookName = "Book";
        public String authorName = "Author";
        public int totalPages = 100;

        public void accept(ItemHandler handler) {
            handler.handle(this);
        }
    }

    public class Magazine implements Item {
        public List papers = new ArrayList();
        public String magazineName = "Magazine";
        public String magazineNo = "1";

        public void accept(ItemHandler handler) {
            handler.handle(this);
        }

        public void addPaper(Paper paper) {
            papers.add(paper);
        }
    }

    public class Paper implements Item {
        public String paperTitle = "Paper";
        public String author = "Author";
        public int pages = 99;

        public void accept(ItemHandler handler) {
            handler.handle(this);
        }
    }

    public class Library {
        Item book = new Book();
        Item magazine = new Magazine();
        Item paper = new Paper();

        public List items = new ArrayList();

        public void addItem(Item item) {
            items.add(item);
        }

        public void removeItem(Item item) {
            items.remove(item);
        }

        public void accept(ItemHandler handler) {
            for (int i = 0; i < items.size(); i++) {
                Item item = (Item) items.get(i);
                item.accept(handler);

            }
        }
    }

    public static void main(String args[]) {
        Test test = new Test();

        Book book = test.new Book();
        book.bookName = "21天精通九阳神功";
        book.authorName = "张无忌";
        book.totalPages = 450;

        Magazine magazine = test.new Magazine();
        magazine.magazineName = "功夫学报";
        magazine.magazineNo = "2011年第1期";
        Paper m_paper_1 = test.new Paper();
        m_paper_1.paperTitle = "九阳神功的历史";
        m_paper_1.author = "张无忌";
        m_paper_1.pages = 10;
        magazine.addPaper(m_paper_1);

        Paper paper1 = test.new Paper();
        paper1.paperTitle = "如何单手制服敌人";
        paper1.author = "杨过";
        paper1.pages = 12;
        Paper paper2 = test.new Paper();
        paper2.paperTitle = "我和杨过的功夫情缘";
        paper2.author = "小龙女";
        paper2.pages = 8;
        Paper paper3 = test.new Paper();
        paper3.paperTitle = "研究报告-靖哥哥的九大弱点";
        paper3.author = "黄蓉";
        paper3.pages = 30;

        Library library = test.new Library();

        library.addItem(book);
        library.addItem(magazine);
        library.addItem(paper1);
        library.addItem(paper2);
        library.addItem(paper3);

        System.out.print("\033[H\033[2J");
        System.out.flush();
        while (true) {
            Scanner scanner = new Scanner(System.in);
            System.out.println("1. PageHandler");
            System.out.println("2. AuthorHandler");
            System.out.println("3. ClearScreen");
            System.out.println("4. Exit");
            System.out.print("Please input your choice: ");
            int choice = scanner.nextInt();
            if (choice == 4) {
                break;
            }
            switch (choice) {
                case 1:
                    library.accept(test.new PageHandler());
                    break;
                case 2:
                    library.accept(test.new AuthorHandler());
                    break;
                case 3:
                    System.out.print("\033[H\033[2J");
                    System.out.flush();
                    break;
                default:
                    System.out.println("Invalid choice!");
                    break;
            }

        }

    }

}

工厂方法模式(创建型)

在某图形库API中提供了多种矢量图模板,用户可以基于这些矢量图创建不同的显示图形,图形库设计人员设计的初始类图如下所示:

image-20230312212216615.png

在该图形库中,每个图形类(如Circle、Triangle等)的init()方法用于初始化所创建的图形, setColor()方法用于给图形设置边框颜色,fill()方法用于给图形设置填充颜色,setSize()方法用于设置图形的大小,display()方法用于显示图形。

客户类(Client)在使用该图形库时发现存在如下问题:

(1) 由于在创建窗口时每次只需要使用图形库中的一种图形,因此在更换图形时需要修改客户类源代码;

(2) 在图形库中增加并使用新的图形时需要修改客户类源代码;

(3) 客户类在每次使用图形对象之前需要先创建图形对象,有些图形的创建过程较为复杂,导致客户类代码冗长且难以维护。

现需要根据面向对象设计原则对该系统进行重构(提示:工厂方法模式),要求如下:

(1) 隔离图形的创建和使用,将图形的创建过程封装在专门的类中,客户类在使用图形时无须直接创建图形对象,甚至不需要关心具体图形类类名;

(2) 客户类能够方便地更换图形或使用新增图形,无须针对具体图形类编程,符合开闭原则。

import java.util.Scanner;

public class Test {

    // Factory类,不负责生产,只是制定生产规则,具体实施交给子类
    public abstract class Shape {
        public abstract void init();

        public abstract void setColor();

        public abstract void fill();

        public abstract void display();
    }

    // 子类,负责生产
    public class Circle extends Shape {
        public Circle() {
            System.out.println("我是圆形");
            init();
            setColor();
            fill();
            display();
        }

        public void init() {
            System.out.println("Circle.init()");
        }

        public void setColor() {
            System.out.println("Circle.setColor()");
        }

        public void fill() {
            System.out.println("Circle.fill()");
        }

        public void display() {
            System.out.println("Circle.display()");
        }
    }

    // 子类,负责生产
    public class Triangle extends Shape {
        public Triangle() {
            System.out.println("我是三角形");
            init();
            setColor();
            fill();
            display();
        }

        public void init() {
            System.out.println("Triangle.init()");
        }

        public void setColor() {
            System.out.println("Triangle.setColor()");
        }

        public void fill() {
            System.out.println("Triangle.fill()");
        }

        public void display() {
            System.out.println("Triangle.display()");
        }
    }

    // 子类,负责生产
    public class rectangle extends Shape {
        public rectangle() {
            System.out.println("我是四边形");
            init();
            setColor();
            fill();
            display();
        }

        public void init() {
            System.out.println("rectangle.init()");
        }

        public void setColor() {
            System.out.println("rectangle.setColor()");
        }

        public void fill() {
            System.out.println("rectangle.fill()");
        }

        public void display() {
            System.out.println("rectangle.display()");
        }

    }

    // 工厂类,负责生产
    public class CreateShape {
        public Shape getShape(String shape) {
            if (shape == null) {
                return null;
            }
            if (shape.equalsIgnoreCase("circle")) {
                return new Circle();
            } else if (shape.equalsIgnoreCase("triangle")) {
                return new Triangle();
            } else if (shape.equalsIgnoreCase("rectangle")) {
                return new rectangle();
            }
            return null;
        }
    }

    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.println("请输入你要生产的图形:");
        String shape = input.nextLine();
        System.out.println("--------------------");
        Test t = new Test();
        CreateShape cs = t.new CreateShape();
        Shape s = cs.getShape(shape);
        System.out.println("--------------------");
    }

}

简单工厂模式:简单工厂模式,又叫静态工厂模式,在Java中专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。简单工厂模式的核心是定义一个创建对象的接口,将对象的创建和本身的业务逻辑分离 ,降低系统的耦合度,使得两个修改起来相对容易些,当以后实现改变时,只需要修改工厂类即可。

下面这个程序的类图为:

image-20230314112925728.png

public class Fish {
    // 抽象产品角色
    public interface Fruit {
        void eat();
    }

    // 具体产品角色
    public class Apple implements Fruit {
        @Override
        public void eat() {
            System.out.println("吃苹果");
        }
    }

    public class Banana implements Fruit {
        @Override
        public void eat() {
            System.out.println("吃香蕉");
        }
    }

    // 工厂角色
    public class FruitFactory {
        // 静态工厂方法
        public Fruit createFruit(String type) {
            if (type.equals("apple")) {
                return new Apple();
            } else if (type.equals("banana")) {
                return new Banana();
            } else {
                return null;
            }
        }
    }

    // 客户端测试
    public static void main(String[] args) {
        Fish fish = new Fish();
        FruitFactory factory = fish.new FruitFactory();
        // 通过工厂类创建苹果对象
        Fruit apple = factory.createFruit("apple");
        apple.eat(); // 输出:吃苹果

        // 通过工厂类创建香蕉对象
        Fruit banana = factory.createFruit("banana");
        banana.eat(); // 输出:吃香蕉

        // 通过错误参数无法创建对象
        Fruit orange = factory.createFruit("orange");
        orange.eat(); // 抛出空指针异常
    }
}

桥接模式:桥接模式是一种设计模式,它可以将抽象和实现分离,让它们可以独立地变化。一个简单的例子是,假设我们有一个形状接口和一个颜色接口,我们想要用不同的颜色来绘制不同的形状。我们可以使用桥接模式来将形状和颜色分离,而不是为每种组合创建一个子类

image-20230314113652046.png

// 颜色接口
interface Color {
    void applyColor();
}

// 红色实现类
class RedColor implements Color {
    public void applyColor() {
        System.out.println("Red color");
    }
}

// 蓝色实现类
class BlueColor implements Color {
    public void applyColor() {
        System.out.println("Blue color");
    }
}

// 形状抽象类,包含一个颜色对象作为桥梁
abstract class Shape {
    protected Color color;

    public Shape(Color color) {
        this.color = color;
    }

    abstract void draw();
}

// 正方形子类
class Square extends Shape {

    public Square(Color color) {
        super(color);
    }

    @Override
    void draw() {
        System.out.print("Square drawn. ");
        color.applyColor();
    }
}

// 三角形子类
class Triangle extends Shape {

    public Triangle(Color color) {
        super(color);
    }

    @Override
    void draw() {
        System.out.print("Triangle drawn. ");
        color.applyColor();
    }
}

public class Fish {

    public static void main(String[] args) {
 
       // 创建两个颜色对象
       Color red = new RedColor();
       Color blue = new BlueColor();
 
       // 创建两个形状对象,并传入颜色对象作为参数
       Shape square = new Square(red);
       Shape triangle = new Triangle(blue);
 
       // 调用绘制方法,输出结果
       square.draw();
       triangle.draw();
 
    }
 }

状态模式:状态模式是一种设计模式,它可以让一个对象在不同的状态下有不同的行为。状态模式可以把复杂的switch语句或者if-else语句转换成对象,使代码更清晰和易维护。

image-20230314111409037.png

// 状态接口
interface State {
    void handle();
}

// 具体状态类
class ConcreteStateA implements State {
    @Override
    public void handle() {
        System.out.println("State A handled.");
    }
}

class ConcreteStateB implements State {
    @Override
    public void handle() {
        System.out.println("State B handled.");
    }
}

// 环境类,持有一个状态对象的引用
class Context {
    private State state;

    public Context(State state) {
        this.state = state;
    }

    public void setState(State state) {
        this.state = state;
    }

    public void request() {
        // 根据当前状态执行不同的操作
        state.handle();
    }
}

// 测试类
public class Fish {

    public static void main(String[] args) {
        // 创建两个具体状态对象
        State stateA = new ConcreteStateA();
        State stateB = new ConcreteStateB();

        // 创建环境对象,并设置初始状态为A
        Context context = new Context(stateA);

        // 调用环境对象的请求方法,会根据当前状态执行不同的操作
        context.request(); // 输出:State A handled.

        // 改变环境对象的状态为B
        context.setState(stateB);

        // 再次调用环境对象的请求方法,会根据当前状态执行不同的操作
        context.request(); // 输出:State B handled.

    }
}