概述
目录
- 00.简单工厂模式
- 1.1 工厂方法模式
- 1.2 抽象工厂模式
- 1.3 生成器模式
- 1.4 原型模式
- 1.5 单例模式
- 2.1 适配器模式
- 2.2 桥接模式
- 2.3 组合模式
- 2.4 装饰模式
- 2.5 外观模式
- 2.6 享元模式
- 2.7 代理模式
- 3.1 责任链模式
- 3.2 命令模式
- 3.3 解释器模式
- 3.4 迭代器模式
- 3.5 中介者模式
- 3.6 备忘录模式
- 3.7 观察者模式
- 3.8 状态模式
- 3.9 策略模式
- 3.10 模板方法模式
- 3.11 访问者模式
00.简单工厂模式
说明:该工厂类可以根据不同的参数,返回不同的实例对象;被创建的对象通常都有一个共同的抽象父类。工厂模式中创建实例的方法是一个静态方法。(类图如下)
举个例子:有一家
饺子店
,店长(工厂)根据客人需求而输入不同的馅料(参数),制作出不同口味的饺子(产品)。
public class m00Factory {
public static void main(String[] args) {
try {
Product pa = Factory.createProduct('A');
pa.info();
Product pb = Factory.createProduct('B');
pb.info();
Factory.createProduct('C');
} catch (Exception e) {
System.err.println("err: 输入参数错误!");
}
}
}
// 产品抽象类
abstract class Product{
public abstract void info();
}
// 产品实现类A
class ProductA extends Product{
@Override
public void info() {
System.out.println("输出产品A");
}
}
// 产品实现类B
class ProductB extends Product{
@Override
public void info() {
System.out.println("输出产品B");
}
}
// 简单工厂模式
class Factory{
public static Product createProduct(char x) throws Exception {
Product p;
switch (x){
case 'A':
p = new ProductA();break;
case 'B':
p = new ProductB();break;
default:
throw new Exception();
}
return p;
}
}
【运行结果】
- 弊端:每次新增一个新的产品,都要修改工厂的判断条件,使其能创建对应的产品实例。
1.1 工厂方法模式
说明:定义一个用于创建对象的接口,让其子类决定实例化的类。既将实例化延迟到期其子类,这样子在新增一个产品时,只要对应的新增一个实现工厂接口的类即可。(类图如下)
举个例子:还是这家
饺子店
,店长(工厂接口)雇佣了若干个店员(工厂实现类),每个店员负责生产一种饺子,客人找到对应的店员下单即可。
public class m01Factory {
public static void main(String[] args) {
Product pa = new FactoryA().createProduct();
pa.info();
Product pb = new FactoryB().createProduct();
pb.info();
}
}
interface Factory{
public Product createProduct();
}
class FactoryA implements Factory{
@Override
public Product createProduct() {
return new ProductA();
}
}
class FactoryB implements Factory{
@Override
public Product createProduct() {
return new ProductB();
}
}
interface Product{
public void info();
}
class ProductA implements Product{
@Override
public void info() {
System.out.println("输出产品A");
}
}
class ProductB implements Product{
@Override
public void info() {
System.out.println("输出产品B");
}
}
【运行结果】
输出产品A
输出产品B
【适用性】
- 当一个类不知道(不确定)他所必须创建的对象类的时候
- 当一个类希望有它的子类来具体指定创建的对象的时候
1.2 抽象工厂模式
说明:提供一个创建一系列相关或相互依赖对象的接口
(抽象工厂),而无须指定其具体的类。(类图如下)
例:还是这家
饺子店
,店长(工厂接口)还是雇佣了若干个店员(工厂实现类),现在每个员工对会制作多种馅料的饺子(多可创建方法)。虽然不同的员工制作一种饺子用的是同一个配方(产品接口),但是各自之间制作出的饺子(对应的产品)各有特色。客户找到自己喜好的员工下单即可。
package model23.m02;
public class m02Factory {
public static void main(String[] args) {
System.out.println("店员001-张三");
Factory f1 = new Factory1();
f1.createProductA().info();
f1.createProductB().info();
System.out.println("店员002-李四");
Factory f2 = new Factory2();
f2.createProductA().info();
f2.createProductB().info();
}
}
//工厂接口
interface Factory{
public ProductA createProductA();
public ProductB createProductB();
}
class Factory1 implements Factory{
@Override
public ProductA createProductA() {
return new ProductA1();
}
@Override
public ProductB createProductB() {
return new ProductB1();
}
}
class Factory2 implements Factory{
@Override
public ProductA createProductA() {
return new ProductA2();
}
@Override
public ProductB createProductB() {
return new ProductB2();
}
}
//产品A玉米饺子
interface ProductA{
public void info();
}
class ProductA1 implements ProductA {
@Override
public void info() {
System.out.println("输出张三制作的玉米饺子");
}
}
class ProductA2 implements ProductA {
@Override
public void info() {
System.out.println("输出李四制作的玉米饺子");
}
}
//产品B
interface ProductB{
public void info();
}
class ProductB1 implements ProductB {
@Override
public void info() {
System.out.println("输出张三制作的鲜肉饺子");
}
}
class ProductB2 implements ProductB {
@Override
public void info() {
System.out.println("输出李四制作的鲜肉饺子");
}
}
【运行结果】
店员001-张三
输出张三制作的玉米饺子
输出张三制作的鲜肉饺子
店员002-李四
输出李四制作的玉米饺子
输出李四制作的鲜肉饺子
1.3 生成器模式
说明:将一个复杂对象的构建与它的表示分离,使同样的构建过程可以创建出不同的表示。(类图如下)
- ConcreteBuilder 实现 Builder 的接口,以构造和装配各个部件
- Director 用来定义 ConcreteBuilder 的执行步骤(实现组件的不同排列)
- Product 是被构造的复杂对象,最终产品通过ConcreteBuilder 返回给 Director
举个例子:还是这个
饺子店
的后厨,厨师(实现类)根据客户的不同的备注需求(导演类),调整食材的咸淡或烹饪顺序,灵活变通生产出满足客户不同需求的产品(产品类)
import java.util.ArrayList;
public class m03Builder {
public static void main(String[] args) {
Director director = new Director();
director.construct();
}
}
//产品生成
class Product{
public ArrayList<String> list = new ArrayList<String>();
//根据接收的参数来添加不同的部件,实现不同的部件有序的排列
void add(String str){
list.add(str);
System.out.println("++ "+str);
}
void show(){
System.out.println("产品部件排列如下:");
for (String s : list)
System.out.println(":"+s);
}
}
//接口-标准
interface Builder{
public void ability1(); //能力1
public void ability2(); //能力2
public Product submit(); //提交项目
}
//实现类-实现操作
class ConcreteBuilder implements Builder{
Product product = new Product();
@Override
public void ability1() {
product.add("添加部件001");
}
@Override
public void ability2() {
product.add("添加部件002");
}
@Override
public Product submit() {
return product;
}
}
//导演
class Director{
public void construct(){
Builder builder = new ConcreteBuilder();
//导演进行指挥
builder.ability2();
builder.ability1();
//导演收到项目并展示
builder.submit().show();
}
}
【运行结果】
++ 添加部件002
++ 添加部件001
产品部件排列如下:
:添加部件002
:添加部件001
【适用性】
- 当创建创建对象的算法应该独立于该对象的组成部分以及装配顺序(方式)时。
- 当构造的过程必须允许被构造的对象有不同的表示时。
1.4 原型模式
说明:原型实例指向创建对象种类,通过复制创建新产品
public class m04Prototype {
public static void main(String[] args) {
Prototype p = new ConcretePrototype("001","zheng");
System.out.println(p.hashCode()+" - "+p);
Prototype clone = (Prototype) p.clone();
System.out.println(clone.hashCode()+" - "+clone);
}
}
interface Prototype{
public Object clone();
}
class ConcretePrototype implements Prototype {
private String id;
private String name;
public ConcretePrototype(){}
public ConcretePrototype(String id, String name) {
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "{" + "id='" + id + ''' + ", name='" + name + ''' + '}';
}
@Override
public Object clone() {
return new ConcretePrototype(this.id,this.name);
}
}
【运行结果】
856419764 - {id='001', name='zheng'}
621009875 - {id='001', name='zheng'}
//注1:p实例是父类引用指向子类对象,故p实例不能调用ConcretePrototype中特有的方法
//注2:clone方法返回值类型是Object,也不能调用实现类特有方法(原理同上)
1.5 单例模式
说明:一个类仅有一个实例、一个全局访问点
public class m05Singleton {
public static void main(String[] args) {
Singleton s1 = Singleton.getSingleton();
s1.sets("001","zheng");
System.out.println("s1"+s1);
Singleton s2 = Singleton.getSingleton();
s1.sets("002","cheng");
System.out.println("s1"+s1);
System.out.println("s2"+s2);
}
}
class Singleton{
private String id;
private String name;
private Singleton() {} //将构造方法私有化,使外部无法通过new创建实例
private static Singleton s = new Singleton(); //只创建一个私有静态对象
public static Singleton getSingleton(){
return s;
}
public void sets(String id,String name) {
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "{" + "id='" + id + ''' + ", name='" + name + ''' + '}';
}
}
【运行结果】
s1{id='001', name='zheng'}
s1{id='002', name='cheng'}
s2{id='002', name='cheng'}
2.1 适配器模式
说明:将一个类的接口转换成客户希望的接口。(类图如下)
- Adapter:通过继承得到Target类的方法,然后实例化Adaptee得到其属性和方法
- 用户实例化Adapter,使用Target原来的接口名称,即可调用Adaptee的方法
举个例子:用户想给自己的手机充电(use接口),但是现在只有一条TypeC的数据线,用户使用适配器(TypeC转USB)即可充电。
//用户手机是use接口,现只有一条typeC数据线。请制作一个适配器!
public class m06Adapter {
public static void main(String[] args) {
System.out.println("用户需要USB输入数据");
Adapter adapter = new Adapter();
adapter.function();
}
}
class USB{
public void function(){
System.out.println("++ USB数据输出");
}
}
class Adapter extends USB{
private TypeC tc = new TypeC();
@Override
public void function() {
System.out.println("---- 适配器 ----");
tc.function();//接收输入数据并做一定的处理后输出
super.function();
System.out.println("-----------------");
}
}
class TypeC{
public void function(){
System.out.println("++TypeC数据输出");
}
}
【运行结果】
需要USB输入数据
---- 适配器 ----
++TypeC数据输出
++转USB数据输出
-----------------
【适用性】
- 要使用一个已存在的类,但其接口不符合要求(不匹配)。
2.2 桥接模式
说明:将抽象的部分与其实现的部分分离,使他们可以独立地变化。(类图如下)
举个例子:每种产品都对应有红、蓝两种颜色,若产品与颜色一一对应将会产生很多个类并且不好管理。桥接模式就是将颜色的抽象成一类,并将颜色作为抽象产品的一个对象属性。这样子我们可以将颜色作为一大类单独管理,每当创建一个产品时就设置其颜色即可。
public class m07BridgePattern {
public static void main(String[] args) {
Product productA1 = new ProductA();
productA1.setName("鸿cx01");
productA1.setColor(new Red());
Product productA2 = new ProductA();
productA2.setName("鸿cx02");
productA2.setColor(new Blue());
productA1.Operation();
productA2.Operation();
}
}
//产品
abstract class Product{
private String name;
protected Color color; //对象属性
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public void setColor(Color color) {this.color = color;}
public abstract void Operation();
}
class ProductA extends Product{
@Override
public void Operation() {
color.OperationImp(this.getName());
}
}
//产品样式
interface Color{
public void OperationImp(String name);
}
class Red implements Color{
@Override
public void OperationImp(String name) {
System.out.println("输出产品 名称:"+name+" 样式:红");
}
}
class Blue implements Color{
@Override
public void OperationImp(String name) {
System.out.println("输出产品 名称:"+name+" 样式:蓝");
}
}
【运行结果】
输出产品 名称:鸿cx01 样式:红
输出产品 名称:鸿cx02 样式:蓝
【适用性】
- 不希望在抽象和它的实现部分之间有一个固定的绑定关系。(程序在运行时可被切换)
- 对一个抽象的实现部分的修改应对客户不产生影响。
2.3 组合模式
说明:将对象合成树型结构以表示“部分-整体”的层次结构。
- component 为组合中对象声明接口:能实现一些默认行为;声明一些口用于访问和管理子组件。
- Leaf是没有子组件的叶子节点对象。
- Composite有子组件的那些组件。
举个例子:Composite可类比为我们项目中的各个组件、Leaf则是不可再分的每一个对象。组件可以包含其他组件和对象,但Leaf不可存储其他的 leaf 和 composite。
import java.util.ArrayList;
import java.util.List;
public class m08Composite {
public static void show(Boolean b){
System.out.println(b?"成功!":"失败!");
}
public static void looks(List<Composite> list,String name){
System.out.print("遍历"+name+" ");
for (Composite composite : list) {
System.out.print(composite.name + " ");
}
System.out.println("");
}
public static void main(String[] args) {
Composite root = new Folder("root");
Composite folder = new Folder("sonFolder");
Composite file = new File("sonFile");
show(root.Add(folder));
show(root.Add(file));
show(folder.Sub(file));
show(file.Add(file));
looks(root.LookOver(),root.name);
}
}
abstract class Composite{
protected String name;
public void printName(){
System.out.println(name);
}
public abstract boolean Add(Composite file);
public abstract boolean Sub(Composite file);
public abstract List<Composite> LookOver();
}
class Folder extends Composite{
private List<Composite> childList = new ArrayList<Composite>();
public Folder(String name) {
System.out.println("创建文件夹:"+name);
this.name=name;
}
@Override
public boolean Add(Composite file) {
System.out.print(this.name+"执行添加操作:");
return childList.add(file);
}
@Override
public boolean Sub(Composite file) {
System.out.print(this.name+"执行删除操作:");
return childList.remove(file);
}
@Override
public List<Composite> LookOver() {
return childList;
}
}
class File extends Composite{
public File(String name) {
System.out.println("创建文件:"+name);
this.name=name;
}
@Override
public boolean Add(Composite file) {
System.out.print(this.name+"执行添加操作:");
return false;
}
@Override
public boolean Sub(Composite file) {
System.out.print(this.name+"执行删除操作:");
return false;
}
@Override
public List<Composite> LookOver() {
return null;
}
}
【运行结果】
创建文件夹:root
创建文件夹:sonFolder
创建文件:sonFile
root执行添加操作:成功!
root执行添加操作:成功!
sonFolder执行删除操作:失败!
sonFile执行添加操作:失败!
遍历root sonFolder sonFile
【适用性】
- 想表示对象的 “部分-整体” 层次结构
2.4 装饰模式
说明:动态的给一个对象添加一些额外的职责。(装饰模式的灵活性更高)
举个例子:Hero定义了一个英雄类,Decorator是装饰抽象类用于存储一个装饰目标对象和扩展装饰类,两者都继承与Component。其只需要在定义完成英雄类之后,将英雄类对象作为红buff装饰类参数,即可为英雄类对象附加装饰类buff。而当buff时间结束时,也可以很方便的剔除buff效果。
public class m09Decorator {
public static void main(String[] args) {
Component hero = new redDecorator(new Hero("亚瑟"));
hero.operation();
}
}
abstract class Component{
protected String name;
abstract public void operation();
}
class Hero extends Component{
public Hero(String name) {
this.name=name;
}
@Override
public void operation() {
System.out.println(name+"是一个王者英雄!");
}
}
abstract class Decorator extends Component{
protected Component obj;
}
//红buff装饰类
class redDecorator extends Decorator{
public redDecorator(Component obj) {
this.obj=obj;
}
@Override
public void operation() {
obj.operation();
System.out.println("+并且 "+obj.name+"有红buff");
}
}
【运行结果】
亚瑟是一个王者英雄!
+并且 亚瑟有红buff
【适用性】
- 可动态的为目标对象添加额外职责,并且添加的职责可方便撤销
2.5 外观模式
说明:为子系统的一组接口提供他有一个一致的界面。
【适用性】
- 为一个复杂的子系统提供一个简单的接口
2.6 享元模式
说明:运行共享技术有效地支持大量细粒度的对象。但并非所有Flyweight子类都必须被共享,这只是让共享变为可能。
举个例子:围棋游戏中,我们需要大量相同的黑白棋。我们对于每一个棋子,只需要记住其位置及颜色即可,并不需要大量的重复的对象时,可通过共享对象以减少系统新建对象的开销。
package model23.m11;
public class m11Flyweight {
public static void main(String[] args) {
Factory f = new Factory(15); //创建一个30*30的棋盘
int mags = 0;
mags = f.putChess(true,10,12);
mag(mags);
mags = f.putChess(false,10,12);
mag(mags);
}
public static void mag(int m){
switch (m){
case 1 :System.out.println("该位置有棋子!");break;
case 2 :System.out.println("棋盘超出范围!");break;
default:break;
}
}
}
class Factory{
private Flyweight white = new whiteChess();//白棋实例
private Flyweight black = new blackChess();//黑棋实例
private int size;
private int[][] arr;
public Factory(int size) {
this.size = size; //初始化,定义棋盘大小
arr = new int[size][size];
for (int[] ints : arr) {
for (int anInt : ints) {
anInt=0;
}
}
}
public int putChess(boolean b, int x, int y){
if(x>size || y>size || x<0 || y<0) return 2;
if(arr[x][y]!=0) return 1;
if (b){//true白棋
arr[x][y]=1;
System.out.println(white.draw(x,y));
return 0;
}
else{ //false黑棋
arr[x][y]=2;
black.draw(x,y);
return 0;
}
}
public int[][] getChessArr(){
return arr;
}
}
abstract class Flyweight{
protected String color;
public abstract String draw(int x,int y);
}
//白棋
class whiteChess extends Flyweight{
public whiteChess() {
this.color="while";
}
@Override
public String draw(int x, int y) {
return "白棋 x="+x+" y="+y;
}
}
//黑棋
class blackChess extends Flyweight{
public blackChess() {
this.color="black";
}
@Override
public String draw(int x, int y) {
return "黑棋 x="+x+" y="+y;
}
}
【运行结果】
白棋 x=10 y=12
该位置有棋子!
//该模块实现了一些操作中的错误判断及记录棋子位置而变得复杂。实际上该demo中的所有棋子,仅用了两个对象实例。与单例模式的区别是单例在定义类的时候直接对无参构造私有化,从而只能有一个实例;而享元模式是在创建一个工厂来提前实例化对象,将对象实例封装在方法中给外部调用,实现对象的贡献。
【适用性】
- 一个应用程序使用了大量的对象,并由于大量的对象造成了巨大的开销
2.7 代理模式
说明:为其他对象提供一种代理以控制对这个对象的访问。(面向切面编程AOP)
注:Proxy不能动态地添加,它强调的是Proxy与它的实体之间的关系。
举个例子:客户希望租房(subject),房东希望出租(realSubject)。整个时候有一个中介来代理房东出租房子,并帮其签合同和收房租,房东只需要将房子交给中介代理即可。
public class m12Proxy {
public static void main(String[] args) {
Proxy proxy = new Proxy(new RealSubject());
proxy.Request();
}
}
interface Subject{
public abstract void Request();//租房请求
}
class Proxy implements Subject{
private RealSubject real;
public Proxy(RealSubject real) {
this.real = real;
}
@Override
public void Request() { //强化租房请求
System.out.println("中介代理签合同!");
real.Request();
System.out.println("中介代理收房租!");
}
}
class RealSubject implements Subject {
@Override
public void Request(){ //实现租房请求
System.out.println("房东出租房子");
}
}
【运行结果】
中介代理签合同!
房东出租房子
中介代理收房租!
3.1 责任链模式
说明:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
举个例子:学生向辅导员请假只能请一周以内,超过一周的辅导员需要提交院长审批。而对学生而言只需要将请求发给辅导员即可,至于辅导员如何转交院长的过程,学生并不需要关心。
public class m13Chain {
public static void main(String[] args) {
Handler c1 = new Concrete1();
Handler c2 = new Concrete2();
c1.setNext(c2); //将c2设置为c1的下一级处理对象
c1.HandlerRequest(12); //12是c1无法处理的,那么c1会将12转发给c2去处理
}
}
abstract class Handler{
protected Handler next; //存储下一级对象
public void setNext(Handler next) {
this.next = next;
}
public abstract void HandlerRequest(int number);
}
class Concrete1 extends Handler{
@Override
public void HandlerRequest(int number) {
if (number<=7){
System.out.println("对象1处理该请求!"+number);
}else if(next!=null){
next.HandlerRequest(number);
}else {
System.out.println("无法处理该请求!");
}
}
}
class Concrete2 extends Handler{
@Override
public void HandlerRequest(int number) {
if (number<=15){
System.out.println("对象2处理该请求!"+number);
}else if(next!=null){
next.HandlerRequest(number);
}else {
System.out.println("无法处理该请求!");
}
}
}
【运行结果】
对象2处理该请求!12
【适用性】
- 多个对象处理一个请求,在不明确接受者的情况下,向其中一个对象发送请求。
3.2 命令模式
说明:将一个请求封装为一个对象,从而使得可以用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持撤销的操作。
举个例子:电视机是命令的接收者,通过一定有规定的集成电路板可向电视发送开机命令。但不可能要求用户直接从操作命令,所以这时候还需要将该命令的发送封装到一个开机按钮上去(命令发送者)。
public class m14Command {
public static void main(String[] args) {
ConcreteCommand crete = new ConcreteCommand(new Receiver());//命令
Invoker invoker = new Invoker();
invoker.setC(crete);
invoker.call();
}
}
//命令发送者:要求该命令执行这个请求
class Invoker{
private Command c;
public void setC(Command c) {
this.c = c;
}
public void call(){
c.Execute();
}
}
//执行操作的接口:命令接口
interface Command{
public void Execute();
}
//将一个接收对象绑定于一个动作
class ConcreteCommand implements Command{
private Receiver r;
public ConcreteCommand(Receiver r) {
this.r = r;
}
@Override
public void Execute() {
r.opened();//开机动作
}
}
//命令接收者
class Receiver{
public void opened(){
System.out.println("打开电视--开机");
}
}
【运行结果】
打开电视
【适用性】
- 抽象出待执行的动作以参数化某对象。
- 在不同的时刻指定、排列和执行请求。
- 支持取消操作、修改日志。
- 有构建的在原语操作上的高层操作构造一个系统
3.3 解释器模式
说明:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
- Terminal:实现与文法中的终结符相关联的解释操作。
- Nonterminal:维护Terminal,为文法中的非终结符实现解释操作。
- Context:解释器之外的一些全局变量。
import java.util.HashSet;
import java.util.Set;
public class m5 {
public static void main(String[] args) {
Context context = new Context();
context.check("A-开发"); //输入正确!
context.check("D-开发"); //输入错误!
}
}
class Context{
private String[] regions= {"A","B","C"};
private String[] persons= {"开发","测试","运维"};
Expression re,pe,te;
public Context() {
re = new Terminalxxx(regions);
pe = new Terminalxxx(persons);
te = new Nonterxxx(re,pe);
}
public void check(String info){
boolean interprey = te.Interprey(info);
if (interprey) System.out.println("输入正确!");
else System.out.println("输入错误!");
}
}
interface Expression{
public boolean Interprey(String info);
}
class Nonterxxx implements Expression{
Expression re,pe; //维护终结符类型解释器
public Nonterxxx(Expression re, Expression pe) {
this.re = re;
this.pe = pe;
}
@Override
public boolean Interprey(String info) {
String[] split = info.split("-");
return re.Interprey(split[0])&&pe.Interprey(split[1]);
}
}
//初始化时将数组录入集合,调用方法判断参数是否在集合中,返回布尔
class Terminalxxx implements Expression{
private Set<String> set = new HashSet<>();
public Terminalxxx(String[] str) {
for (String s : str) {
set.add(s);
}
}
@Override
public boolean Interprey(String info) {
return set.contains(info);
}
}
【适用性】
- 文法简单。
- 效率不是一个关键的问题。
3.4 迭代器模式
说明:提供一种方法顺序访问一个聚合对象中的各个元素,且不需要暴露该对象的内部表示。
- ConcreteAggregate(聚合对象):实现创建相应迭代器接口。
- ConcreteIterator(迭代器对象):遍历时跟踪当前位置。
import java.util.ArrayList;
import java.util.List;
public class m16 {
public static void main(String[] args) {
String[] names = {"数据库概述","数据结构","操作系统","计算机组成原理"};
String[] prices = {"23.43","43.23","12.40","26.90"};
bookAggregate books = new bookAggregate(); //book聚合对象
//创建book对象并存储到聚合对象中
for (int i = 0; i < 4; i++) {
boolean add = books.add(new Book(names[i], prices[i]));
if (!add){
System.out.println("对象传入集合失败,程序中断!");
System.exit(0);
}
}
//获取迭代器对象
Iterator iterator = books.CreateIterator();
while (iterator.next()){
Book data = iterator.data();
System.out.println(data.getName()+"="+data.getPrice());
}
}
}
//迭代器
interface Iterator{
public boolean next();//判断是否还有下一个对象
public Book data();//获取对象
}
class bookIterator implements Iterator{
private bookAggregate books;
private int index=0;
public bookIterator(bookAggregate books) {
this.books = books;
}
@Override
public boolean next() {
return index<books.getSize();
}
@Override
public Book data() {
Book book = books.getBook(index);
index++;
return book;
}
}
//聚合对象
interface Aggregate{
public Iterator CreateIterator();
}
class bookAggregate implements Aggregate{
List<Book> list = new ArrayList<>();
public boolean add(Book b){
return list.add(b);
}
public Book getBook(int index){
return list.get(index);
}
public int getSize(){
return list.size();
}
@Override
public Iterator CreateIterator() {
return new bookIterator(this);
}
}
//对象实体
class Book{
private String name;
private String price;
public Book(String name, String price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public String getPrice() {
return price;
}
}
【运行结果】
数据库概述:23.43
数据结构:43.23
操作系统:12.40
计算机组成原理:26.90
【适用性】
- 访问一个聚合对象的内容而无需暴露其内部
- 支持对聚合对象多种遍历方式
- 为遍历不用的聚合结构提供一个统一的接口
3.5 中介者模式
说明:用一个中介对象来封装一系列的对象交互。中介者使对象不需要显示地相互引用,使得耦合松散,可独立的改变它们之间的交互。
举个例子:当许多对象需要进行通信时,让对象两两建立联系会产生许多的联系。中介者则是在其中间帮忙传达,在帮助对象与其他对象建立通信。
import java.util.ArrayList;
import java.util.List;
public class m17 {
public static void main(String[] args) {
//实例化中介者
ConcreteMediator mediator = new ConcreteMediator();
colleague coworka = new colleagueA(mediator);
colleague coworkb = new colleagueB(mediator);
mediator.inputs(coworka,coworkb);
coworka.send("coworka发送信息001",1);
System.out.println("-------------");
coworka.send("coworka发送信息002",0);
}
}
//中介者
abstract class Mediator{
List<colleague> list = new ArrayList<>();
//初始化中介者,将有关对象实例存入其中
public void inputs(colleague...coll) {
for (colleague colleague : coll) {
list.add(colleague);
}
}
//消息 , 发送者 , 接收者
public abstract boolean transmit(String msg,colleague send,int receive);
}
class ConcreteMediator extends Mediator{
@Override
public boolean transmit(String msg, colleague send, int receive) {
//判断发送与接收对象是否为同一个,是则终止
if (list.get(receive).equals(send))return false;
//转发信息
list.get(receive).receive(msg);
return true;
}
}
//实体对象
abstract class colleague{
Mediator mediator;
public abstract void send(String msg,int end);
public abstract void receive(String msg);
}
class colleagueA extends colleague{
public colleagueA(ConcreteMediator mediators) {
this.mediator=mediators;
}
@Override
public void send(String msg, int end) {
if (!mediator.transmit(msg,this,end)){
System.out.println("colleagueA发送失败!");
}else {
System.out.println("colleagueA发送成功!");
}
}
@Override
public void receive(String msg) {
System.out.println("colleagueA接收信息:"+msg);
}
}
class colleagueB extends colleague{
public colleagueB(ConcreteMediator mediators) {
this.mediator=mediators;
}
@Override
public void send(String msg, int end) {
if (!mediator.transmit(msg,this,end)){
System.out.println("colleagueB发送失败!");
}else {
System.out.println("colleagueB发送成功!");
}
}
@Override
public void receive(String msg) {
System.out.println("colleagueB接收信息:"+msg);
}
}
【运行结果】
colleagueB接收信息:coworka发送信息001
colleagueA发送成功!
-------------
colleagueA发送失败!
【适用性】
- 一组对象以良好但复杂的方式进行通信时,产生了混乱的相互依赖(难以维护)。
- 一个对象引用了其他对象并且直接与这些对象通信,导致难以复用。
3.6 备忘录模式
说明:在不破坏封装性的前提下捕获一个对象的内部状态,并在对象之外保存这个状态。状态就可以将对象恢复到原先的保存状态。
- Originator 原发器:创建一个备忘录,用于记录当前状态
- Memento 备忘录:存储原发器状态
- Caretaker 管理者:保存备忘录
举个例子:当我们的程序(原发器)在运行过程中发生中断时(IO中断/缺页中断)。我们需要保存(备忘录)当前程序的状态,先让cpu去处理其他的程序后再放回当前程序,恢复状态后继续执行。当然我们也可能在紧急处理的程序中也发生中断,使用需要一个栈(管理者)来保存多个备忘录。
import java.util.ArrayList;
import java.util.List;
public class m18 {
public static void main(String[] args) {
Originator originator = new Originator();
Memento memento;
Caretaker caretaker = new Caretaker();
originator.setState("1024");//设置状态为1024
memento = originator.createMemento();//创建1024备忘录
caretaker.addList(memento);//添加备忘录
originator.setState("2048");
memento = originator.createMemento();
caretaker.addList(memento);//添加备忘录
originator.setState("3072");
memento = originator.createMemento();
caretaker.addList(memento);//添加备忘录
caretaker.showList();//展示备忘录记录
System.out.println("当前原发器状态:"+originator.getState());
memento = caretaker.getList(1);
originator.SetMemento(memento);
System.out.println("当前原发器状态:"+originator.getState());
}
}
//原发器
class Originator{
private String state;
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
//设置原发器状态
public void SetMemento(Memento m){
state=m.getState();
}
//创建备忘录
public Memento createMemento(){
return new Memento(state);
}
}
//备忘录
class Memento{
private String state;
public Memento(String state) {
this.state = state;
}
public String getState() {
return state;
}
}
//管理者
class Caretaker{
List<Memento> list = new ArrayList<>();
public boolean addList(Memento m){
return list.add(m);
}
public Memento getList(int index){
return list.get(index-1);
}
public void showList(){
System.out.println("备忘录记录------");
int i=0;
for (Memento memento : list)
System.out.println("第"+(++i)+"个 "+memento.getState());
}
}
【运行结果】
备忘录记录------
第1个 1024
第2个 2048
第3个 3072
当前原发器状态:3072
当前原发器状态:1024
【适用性】
- 必须保存一个对象在某时某刻的状态,用于后续恢复状态
- 不破坏封装性的基础上(不暴露对象细节)暂存状态。
3.7 观察者模式
说明:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所依赖于它的对象都会得到更新。
举个例子:当粉丝关注了某一个up主,当up主发动态的时候,就会发送一个通知为所有关注他的粉丝。
import java.util.ArrayList;
import java.util.List;
public class m19 {
public static void main(String[] args) {
Observer c1 = new ConcreteObserver("xx001");
Observer c2 = new ConcreteObserver("xx002");
Observer c3 = new ConcreteObserver("xx003");
Subject subject = new ConcreteSuject();
subject.Attach(c1);
subject.Attach(c2);
subject.Attach(c3);
System.out.println("目标状态:"+subject.getState());
subject.setState("更新中...");//设置状态为更新中
System.out.println("目标状态:"+subject.getState());
subject.Detach(c2); //解除一个观察者c2
subject.setState("更新完成");//设置状态为更新完成
System.out.println("目标状态:"+subject.getState());
}
}
//目标对象
interface Subject{
public void Attach(Observer o);//添加观察者
public void Detach(Observer o);//移除观察者
public void Notify(); //向观察者发送通知
public void setState(String state); //设置当前状态
public String getState(); //获取当前状态
}
class ConcreteSuject implements Subject{
private String state; //记录当前状态
//声明一个集合存储多个观察者
private List<Observer> list = new ArrayList<>();
public ConcreteSuject() {
state="初始化状态";
}
@Override
public void Attach(Observer o) {
list.add(o);
}
@Override
public void Detach(Observer o) {
list.remove(o);
}
@Override
public void Notify() {
for (Observer observer : list) {
observer.update(state);
}
}
@Override
public void setState(String state) {
this.state=state;
Notify();
}
@Override
public String getState() {
return state;
}
}
//观察者
interface Observer{
public void update(String state);//接收更新通知
}
class ConcreteObserver implements Observer{
private String state;
private String uid;
public ConcreteObserver( String uid) {
this.state = "初始状态";
this.uid = uid;
}
@Override
public void update(String state) {
this.state=state;
System.out.println(uid+"收到更新通知!"+state);
}
}
【运行结果】
目标状态:初始化状态
xx001收到更新通知!更新中...
xx002收到更新通知!更新中...
xx003收到更新通知!更新中...
目标状态:更新中...
xx001收到更新通知!更新完成
xx003收到更新通知!更新完成
目标状态:更新完成
【适用性】
3.8 状态模式
说明:允许一个对象在其内部状态改变时改变它的行为。
举个例子:一个售卖机(上下文)在运行的过程中,可能出现售空(状态1)和有货(状态2)的状态,需要根据不同情况为该售卖机设置状态
public class m20 {
public static void main(String[] args) {
Context context = new Context(0, new StateA());
context.buy(); //买,失败
Boolean addc = context.addCount(2); //补货
if (addc) System.out.println("补货成功!");
else System.out.println("补货失败!");
context.buy(); //买,成功
context.buy(); //买,成功
context.buy(); //买,失败
context.buy(); //买,失败
}
}
//上下文对象--售卖机
class Context{
private int count;
private State state;
public Context(int count, State state) {
this.count = count;
this.state = state;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public void setState(State state) {
this.state = state;
}
//补货
public Boolean addCount(int count) {
if (count>0) {
this.count = count;
return true;
}
return false;
}
//买
public void buy(){
state.Handle(this);
}
}
//状态
interface State{
public void Handle(Context c);
}
class StateA implements State{ //有货
@Override
public void Handle(Context c) {
int count = c.getCount();
if (count>0){
System.out.println("出货成功! 存量:"+(count-1));
c.setCount(count-1);
}else {
System.out.println("出货失败!执行退款操作");
c.setState(new StateB());
}
}
}
class StateB implements State{ //无货
@Override
public void Handle(Context c) {
if (c.getCount()>1){
State stateA = new StateA();
c.setState(stateA);
stateA.Handle(c);//转发给有货状态
}else {
System.out.println("无货!等待补货..");
}
}
}
【运行结果】
出货失败!执行退款操作
补货成功!
出货成功! 存量:1
出货成功! 存量:0
出货失败!执行退款操作
无货!等待补货..
【适用性】
- 一个对象的行为决定于它的状态,并且必须在运行时根据状态改变它的行为
- 一个操作中含大量分支条件语句,其这些分支依赖于该对象的状态。
3.9 策略模式
说明:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。
举个例子:例如前端开发中,往往开发阶段和生产阶段所使用的不是同一个接口,一个项目(上下文)的开发,往往对应入开发、测试、生产等多套接口(多个策略)
public class m21 {
public static void main(String[] args) {
Strategy a = new StrategyA(); //开发
Strategy b = new StrategyB(); //生产
Context context;
context = new Context(a);
context.operation();
context = new Context(b);
context.operation();
}
}
//上下文
class Context{
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public void operation(){
System.out.println("状态模式:"+strategy.function());
}
}
//策略接口
interface Strategy{
public String function();
}
//策略A
class StrategyA implements Strategy{
@Override
public String function() {
return "开发模式";
}
}
//策略B
class StrategyB implements Strategy{
@Override
public String function() {
return "生产模式";
}
}
【运行结果】
状态模式:开发模式
状态模式:生产模式
3.10 模板方法模式
说明:定义一个操作中的算法骨架,而将一些步骤延迟到子类中。
public class m22 {
public static void main(String[] args) {
concrete c = new concrete();
c.Template();
}
}
abstract class Abstract{
//模板方法
public void Template(){
System.out.println("模板固定上下文1");
operation1();
System.out.println("模板固定上下文2");
operation2();
}
//原语1
public abstract void operation1();
//原语2
public abstract void operation2();
}
class concrete extends Abstract{
@Override
public void operation1() {
System.out.println("对象A实现了原语1");
}
@Override
public void operation2() {
System.out.println("对象A实现了原语2");
}
}
【运行结果】
模板固定上下文1
对象A实现了原语1
模板固定上下文2
对象A实现了原语2
【适用性】
- 一次性实现算法中不变的部分,将需要改变的部分交给子类去实现。
- 将公共部分提取出来,以免代码重复。(不方便通过传参)
3.11 访问者模式
说明:表示一个作用于某对象结构中的各个元素的操作。它允许在不改变元素的类的前提下定义作用于这些元素的新操作。
举个例子:为图书馆添加一个查询所有书籍及文献页数和的操作,只需要让访问者遍历每一本书并记录求和即可。
package model23.m23;
import java.util.ArrayList;
import java.util.List;
public class m23 {
public static void main(String[] args) {
LibraryVisitor visitor = new SumPrintVisitor();
Library library = new Library();
library.foreach(visitor);
}
}
class Library{
List<LibraryItem> list = new ArrayList<>();
public Library() {
Book b1 = new Book("aaa", "001", 268);
list.add(b1);
Book b2 = new Book("aaa", "001", 345);
list.add(b2);
Article a1 = new Article("asda", "bbb", 80, 5);
list.add(a1);
}
public void foreach(LibraryVisitor visitor){
for (LibraryItem libraryItem : list) {
libraryItem.accept(visitor);
}
visitor.printSum();
}
}
interface LibraryVisitor{
void visit(Book p_book);
void visit(Article P_article);
void printSum();
}
class SumPrintVisitor implements LibraryVisitor{
private int sum = 0;
@Override
public void visit(Book P_book) {
sum+=P_book.getNum();
}
@Override
public void visit(Article P_article) {
sum+=P_article.getNum();
}
@Override
public void printSum() {
System.out.println("sum_pape="+sum);
}
}
abstract class LibraryItem{
abstract void accept(LibraryVisitor visitor);
}
class Book extends LibraryItem{
private String itemName;
private String author;
private int papes; //页数
public Book() {}
public Book(String itemName, String author, int papes) {
this.itemName = itemName;
this.author = author;
this.papes = papes;
}
@Override
void accept(LibraryVisitor visitor) {
visitor.visit(this);
}
int getNum(){
return papes;
}
}
class Article extends LibraryItem{
private String itemName;
private String author;
private int papes; //页数
private int start_papes;
public Article() {}
public Article(String itemName, String author, int papes, int start_papes) {
this.itemName = itemName;
this.author = author;
this.papes = papes;
this.start_papes = start_papes;
}
@Override
void accept(LibraryVisitor visitor) {
visitor.visit(this);
}
int getNum(){
return papes - start_papes;
}
}
最后
以上就是陶醉鞋垫为你收集整理的软考-23种设计模式的全部内容,希望文章能够帮你解决软考-23种设计模式所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复