复习设计模式
访问者模式- 简单工厂模式
工厂方法模式- 桥接模式
- 状态模式
两种适配器模式
中介者模式
策略模式
访问者模式(行为型)图书管理系统中,需要处理每一个书库中资料的页数和作者等信息。书库中的资料包括图书、期刊和论文,其中有些论文是独立存在的,有些论文作为期刊的一部分。使用访问者模式设计该系统,类图如下所示:
在上图中,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中提供了多种矢量图模板,用户可以基于这些矢量图创建不同的显示图形,图形库设计人员设计的初始类图如下所示:
在该图形库中,每个图形类(如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中专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。简单工厂模式的核心是定义一个创建对象的接口,将对象的创建和本身的业务逻辑分离 ,降低系统的耦合度,使得两个修改起来相对容易些,当以后实现改变时,只需要修改工厂类即可。
下面这个程序的类图为:
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(); // 抛出空指针异常
}
}
桥接模式:桥接模式是一种设计模式,它可以将抽象和实现分离,让它们可以独立地变化。一个简单的例子是,假设我们有一个形状接口和一个颜色接口,我们想要用不同的颜色来绘制不同的形状。我们可以使用桥接模式来将形状和颜色分离,而不是为每种组合创建一个子类
// 颜色接口
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语句转换成对象,使代码更清晰和易维护。
// 状态接口
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.
}
}