目录
参考于
学习网站 :
https://refactoringguru.cn/design-patterns/catalog
https://www.runoob.com/design-pattern/design-pattern-intro.html
https://www.bilibili.com/video/BV1pg411n7Ug
idea创建项目
创建空项目
https://blog.csdn.net/qq_44537956/article/details/123075134
设计模式
设计模式出现的原因:
某些问题重复的出现
不用重复设计
将软件中变化的部分和不变的部分 分开 = 高内聚 低耦合
设计模式:
创建性模式
结构性模式
行为性模式
创建型模式:
原型模式
单例模式
简单工厂模式
工厂方法模式
抽象工厂模式
结构性模式:
适配器模式
外观模式
代理模式
装饰模式
桥模式
组合模式
享元模式
行为性模式:
观察者模式
状态模式
模板方法模式
策略模式
职责链模式
命令模式
访问者模式
调停者模式
备忘录模式
迭代器模式
解释器模式
面向对象的设计原则
正交4原则:
最小化重复
分离变化
缩小依赖范围
向稳定方向依赖
SOLID (面向对象设计)
在面向对象发展过程中,提出更具体的SOLID原则(5个):
单一职责(SRP)
开闭原则:向扩展开放,向修改封闭(OCP)
里氏替换原则:子类要能替换父类(LSP)
接口分离原则:接口隔离/最小化接口依赖(ISP)
依赖倒置原则:依赖倒置/只依赖接口(DIP)
迪米特法则 = 最少知道原则:一个类不应知道自己操作的类的细节,换言之,只和朋友谈话,不和朋友的朋友谈话
学习网址:
https://shusheng007.top/2021/09/07/design-pattern/
https://mp.weixin.qq.com/s/n3vsRQZPe0j5oIOk3umj7A
模板模式
策略模式
https://blog.csdn.net/LoveLion/article/details/17517213
创建型模式
单例模式
1个类,在 1 个JVM里,只有 1 个实例存在
饿汉式:立即加载,无论是否会用到该对象,都加载
懒汉式,延迟加载,用的时候才加载;线程安全
启动时,比饿汉式略快,因为没做对象的实例化。
但第 1 次调用时,会实例化操作,感觉上略慢。
看业务需求,如果业务上允许有比较充分的启动和初始化时间,就使用饿汉式,否则就使用懒汉式
3 要素:
1 构造方法私有化
2 静态属性指向实例
3 public static 的 getTest 方法,返回第 2 步的静态属性
饿汉式
私有化构造方法,使得在外面无法通过 new 实例化
该类不能被继承
package 第1个程序.a9_单例模式;
// 饿汉式
public class GD {
private GD(){}
private static GD test = new GD();
public static GD getInstance(){
return test;
}
public static void main(String[] args) {
GD g = new GD();
GD g1 = GD.getInstance();
GD g2 = GD.getInstance();
GD g3 = GD.getInstance();
System.out.println(g1==g2);
System.out.println(g2==g3);
}
}
GD g = new GD();
不会执行,可能报错,不过我本地没有报错
懒汉式
package 第1个程序.a9_单例模式;
// 懒汉式
public class GD2 {
private GD2(){}
private static GD2 test;
public static GD2 getInstance(){
if(test == null){
test = new GD2();
}
return test;
}
public static void main(String[] args) {
GD2 g1 = GD2.getInstance();
GD2 g2 = GD2.getInstance();
GD2 g3 = GD2.getInstance();
System.out.println(g1==g2);
System.out.println(g2==g3);
}
}
练习
package 第1个程序.a9_单例模式;
public class Hero {
private Hero(){}
private static Hero hero = new Hero();
private static Hero getInstance(){
return hero;
}
public static void main(String[] args) {
Hero hero = Hero.getInstance();
}
}
package 第1个程序.a9_单例模式;
public class Hero2 {
private Hero2(){}
private static Hero2 hero = new Hero2();
private static Hero2 getInstance(){
if(hero == null){
hero = new Hero2();
}
return hero;
}
public static void main(String[] args) {
Hero2 hero = Hero2.getInstance();
}
}
工厂模式
简单工厂模式
工厂方法模式
抽象工厂模式,依次抽象
工厂方法模式:
有一个抽象产品类,可以派生多个具体产品类
有一个抽象工厂类,可以派生多个具体工厂类
具体工厂类只能创建一个具体产品类的实例
抽象工厂模式:
每一个抽象产品类可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类可以创建多个具体产品类的实例。
工广方法、抽象工厂模式的区别:
工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。
工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。
原始模式:
class bmw320{
public bmw320(){
System.out.println("制造bmw320");
}
}
class bmw520{
public bmw520(){
System.out.println("制造bmw520");
}
}
public class test {
public static void main(String[] args) {
bmw320 b1 = new bmw320();
bmw520 b2 = new bmw520();
}
}
简单工厂模式:
// 产品类
abstract class bmw{
public bmw(){}
}
class bmw320 extends bmw{
public bmw320(){
System.out.println("制造bmw320");
}
}
class bmw520 extends bmw{
public bmw520(){
System.out.println("制造bmw520");
}
}
//工厂类
class factory{
public bmw creat(int type){
switch (type){
case 320:
return new bmw320();
case 520:
return new bmw520();
default:
break;
}
return null;
}
}
public class test2 {
public static void main(String[] args) {
factory f = new factory();
bmw320 b1 = (bmw320) f.creat(320);
bmw520 b2 = (bmw520) f.creat(520);
}
}
工厂方法模式:
// 产品类
abstract class bmw{
public bmw(){}
}
class bmw320 extends bmw {
public bmw320(){
System.out.println("制造bmw320");
}
}
class bmw520 extends bmw {
public bmw520(){
System.out.println("制造bmw520");
}
}
// 工厂类
interface factory{
public bmw crrat();
}
class factorybmw320 implements factory{
@Override
public bmw crrat() {
return new bmw320();
}
}
class factorybmw520 implements factory{
@Override
public bmw crrat() {
return new bmw520();
}
}
public class test {
public static void main(String[] args) {
factorybmw320 f1 = new factorybmw320();
factorybmw520 f2 = new factorybmw520();
f1.crrat();
f2.crrat();
}
}
抽象工厂模式:
// 发动机
interface engine{}
class engine_a implements engine{
public engine_a(){
System.out.println("制造engine_a");
}
}
class engine_b implements engine{
public engine_b(){
System.out.println("制造engine_b");
}
}
// 空调
interface aircondition{}
class aircondition_a implements aircondition{
public aircondition_a(){
System.out.println("制造aircondition_a");
}
}
class aircondition_b implements aircondition{
public aircondition_b(){
System.out.println("制造aircondition_b");
}
}
// 工厂类
interface factory{
public engine crrat_engine();
public aircondition crrat_aircondition();
}
class factorybmw320 implements factory {
@Override
public engine crrat_engine() {
return new engine_a();
}
@Override
public aircondition crrat_aircondition() {
return new aircondition_a();
}
}
class factorybmw520 implements factory {
@Override
public engine crrat_engine() {
return new engine_b();
}
@Override
public aircondition crrat_aircondition() {
return new aircondition_b();
}
}
public class test {
public static void main(String[] args) {
factorybmw320 f1 = new factorybmw320();
factorybmw520 f2 = new factorybmw520();
f1.crrat_engine();
f1.crrat_aircondition();
f2.crrat_engine();
f2.crrat_aircondition();
}
}
原型模式 prototype
核心:创建重复的对象
存在一个对象,并希望生成与其完全相同的一个复制品
想法:
新建1个属于相同类的对象
遍历原始对象的所有成员变量,将成员变量值复制到新对象中
两个小问题:
1 有些对象拥有私有
成员变量,它们在对象本身以外是不可见的 (并非所有对象都能通过这种方式进行复制)
2 有时你只知道对象所实现的接口,而不知道其所属的具体类,“从外部” 复制对象并非总是可行
3 new产生的一个对象需要非常繁琐的过程(数据准备,访问权限等)
原型模式:采取 复制原型对象的方法 来创建对象的实例,不适用new,用clone
https://juejin.cn/post/6963416852647116807:
public class SkuSold {
private Long skuId;
private Long skuSold;
pubLic SkuSold(Long skuId,Long skuSold) {
this.skuId = skuId;
this skuSold = skuSold;
}
// 省略Get和Set方法
}
public class ItemSold implements Cloneable {
private Long itemId;
private Long sold;
private List<SkuSold> skuSolds;
@Override
protected Object clone() throwsCloneNotSupportedException {
return super.clone( );
}
// 省略Get和Set方法
}
ItemSold clone = (ItemSold)itemsold.clone();
public class testMain {
public static void main(String[]args) throws CloneNotSupportedException {
//这里是从redis中获取的数据
Map<Long,ItemSold> returnMap =new HashMap<>();
//这里是从DB中查询的数据
List<ItemSold> getResultFromDb= getResultFromDb(new Date());
for (ItemSold itemSold : getResultFromDb){
ItemSold clone = (ItemSold)itemsold.clone();
//组装返回数据
returnMap.put(itemSold.getItemId(), clone);
}
}
public static List<ItemSold>getResultFromDb(Date updateTime)throws CloneNotSupportedException {
//假设这里是根据updateTime 条件从DB中获取的数据
List<ItemSold> result = newArrayList<>();
ItemSold itemSold = new ItemSold();
itemSold.setSold(1L);
itemSold.setItemId(1L);
itemSold.setSkuSolds(Collections.singletonList(new SkuSold(3L,3L)));
result.add(itemSold);
return result;
}
}
Java变量分为 原始类型、引用类型(类)
浅拷贝:复制原始类型(int long),复制引用类型(类)的地址引用 = 指针
= 看似多个对象,实则1个对象有多个名字
深拷贝:引用对象类型 完全的复制一份到新的对象
深拷贝:
法1 通用
public class SkuSold implements Cloneable{
private Long skuId;
private Long skuSold;
pubLic SkuSold(Long skuId,Long skuSold) {
this.skuId = skuId;
this skuSold = skuSold;
}
@Override
protected SkuSold/Object clone() throwsCloneNotSupportedException {
return super.clone( );
}
// 省略Get和Set方法
}
public class ItemSold implements Cloneable {
private Long itemId;
private Long sold;
private List<SkuSold> skuSolds;
@Override
protected ItemSold clone() throwsCloneNotSupportedException {
ItemSold clone = super.clone( );
List<SkuSod> skuSolds = clone.getSkuSolds();
List<SkuSod> skuSoldsCopy = newArrayList<>();
for (SkuSold skuSod :skuSolds){
skuSoldsCopy.add((SkuSold)skuSold.clone();
}
clone.setSkuSolds(skuSoldsCopy);
return clone;
}
// 省略Get和Set方法
}
法2 通过序列化把对象写入流中再从流中取出来
public class ItemSod implementsSerializable {
private Long itemId;
private Long sold;
private List SkuSold> skuSolds;
@SneakyThrows
Qoverride
protected Object clone() throwsCloneNotSupportedException {
ByteArray0utputStream bao = newByteArrayOutputStream( );
ObjectoutputStream oos = new ObjectOutputStream(bao)
oos.write0bject(this);
ByteArrayInputStream bis = newByteArrayInputStream(bao.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return (ois.readobject();
}
//省略set和get方法
}
建造者模式 Builder pattern
当一个类的构造函数参数个数超过4个,而且这些参数有些是可选的参数,考虑使用构造者模式
public class Computer {
private String cpu;//必须
private String ram;//必须
private int usbCount;//可选
private String keyboard;//可选
private String display;//可选
}
不用 Builder 的办法:
法1 折叠构造函数模式,参数容易传混:
public class Computer {
...
public Computer(String cpu, String ram) {
this(cpu, ram, 0);
}
public Computer(String cpu, String ram, int usbCount) {
this(cpu, ram, usbCount, "罗技键盘");
}
public Computer(String cpu, String ram, int usbCount, String keyboard) {
this(cpu, ram, usbCount, keyboard, "三星显示器");
}
public Computer(String cpu, String ram, int usbCount, String keyboard, String display) {
this.cpu = cpu;
this.ram = ram;
this.usbCount = usbCount;
this.keyboard = keyboard;
this.display = display;
}
}
法2 Javabean 模式,多线程不安全:
线程A: 获取person,对其name age sex 就行set操作
线程B: 获取person,对其进行get操作
这时候会出现一种情况,在线程A中没有set完毕,线程B 就开始取相应的属性
public class Computer {
...
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;
}
public int getUsbCount() {
return usbCount;
}
...
}
build:
public class Computer {
private final String cpu;//必须
private final String ram;//必须
private final int usbCount;//可选
private final String keyboard;//可选
private final String display;//可选
private Computer(Builder builder){
this.cpu=builder.cpu;
this.ram=builder.ram;
this.usbCount=builder.usbCount;
this.keyboard=builder.keyboard;
this.display=builder.display;
}
public static class Builder{
private String cpu;//必须
private String ram;//必须
private int usbCount;//可选
private String keyboard;//可选
private String display;//可选
public Builder(String cup,String ram){
this.cpu=cup;
this.ram=ram;
}
public Builder setUsbCount(int usbCount) {
this.usbCount = usbCount;
return this;
}
public Builder setKeyboard(String keyboard) {
this.keyboard = keyboard;
return this;
}
public Builder setDisplay(String display) {
this.display = display;
return this;
}
public Computer build(){
return new Computer(this);
}
}
//省略getter方法
}
使用:
Computer computer = new Computer.Builder("因特尔","三星")
.setDisplay("三星24寸")
.setKeyboard("罗技")
.setUsbCount(2)
.build();
标准流程:
Product: 最终要生成的对象,如 Computer实例。
Builder: 构建者的抽象基类(有时会使用接口代替)。定义了构建Product的抽象步骤,其实体类需要实现这些步骤。其会包含一个用来返回最终产品的方法Product getProduct()
ConcreteBuilder: Builder的实现类
Director: 决定如何构建最终产品的算法。void Construct(Builder builder) 负责组装,它通过调用builder的方法,就可以设置builder,通过builder的 getProduct() 方法获得最终的产品
Computer类
public class Computer {
private String cpu;//必须
private String ram;//必须
private int usbCount;//可选
private String keyboard;//可选
private String display;//可选
public Computer(String cpu, String ram) {
this.cpu = cpu;
this.ram = ram;
}
public void setUsbCount(int usbCount) {
this.usbCount = usbCount;
}
public void setKeyboard(String keyboard) {
this.keyboard = keyboard;
}
public void setDisplay(String display) {
this.display = display;
}
@Override
public String toString() {
return "Computer{" +
"cpu='" + cpu + '\'' +
", ram='" + ram + '\'' +
", usbCount=" + usbCount +
", keyboard='" + keyboard + '\'' +
", display='" + display + '\'' +
'}';
}
}
构建者类
public abstract class ComputerBuilder {
public abstract void setUsbCount();
public abstract void setKeyboard();
public abstract void setDisplay();
public abstract Computer getComputer();
}
苹果电脑构建者类、联想电脑构建者类:
public class MacComputerBuilder extends ComputerBuilder {
private Computer computer;
public MacComputerBuilder(String cpu, String ram) {
computer = new Computer(cpu, ram);
}
@Override
public void setUsbCount() {
computer.setUsbCount(2);
}
@Override
public void setKeyboard() {
computer.setKeyboard("苹果键盘");
}
@Override
public void setDisplay() {
computer.setDisplay("苹果显示器");
}
@Override
public Computer getComputer() {
return computer;
}
}
public class LenovoComputerBuilder extends ComputerBuilder {
private Computer computer;
public LenovoComputerBuilder(String cpu, String ram) {
computer=new Computer(cpu,ram);
}
@Override
public void setUsbCount() {
computer.setUsbCount(4);
}
@Override
public void setKeyboard() {
computer.setKeyboard("联想键盘");
}
@Override
public void setDisplay() {
computer.setDisplay("联想显示器");
}
@Override
public Computer getComputer() {
return computer;
}
}
指导者类(Director)
public class ComputerDirector {
public void makeComputer(ComputerBuilder builder){
builder.setUsbCount();
builder.setDisplay();
builder.setKeyboard();
}
}
public static void main(String[] args) {
ComputerDirector director=new ComputerDirector();//1
ComputerBuilder builder=new MacComputerBuilder("I5处理器","三星125");//2
director.makeComputer(builder);//3
Computer macComputer=builder.getComputer();//4
System.out.println("mac computer:"+macComputer.toString());
ComputerBuilder lenovoBuilder=new LenovoComputerBuilder("I7处理器","海力士222");
director.makeComputer(lenovoBuilder);
Computer lenovoComputer=lenovoBuilder.getComputer();
System.out.println("lenovo computer:"+lenovoComputer.toString());
}
结构性模式
适配器模式 adapter
适配器模式:两个类可以一起工作
类的适配器
对象的适配器
类的适配器:一个类 extend一个抽象类、implements一个接口
// 目标类
interface target{
public void v1();
public void v2();
}
// 源
class adaptee{
public void v1(){
System.out.println("v1");
}
}
// 适配器类
class adapter extends adaptee implements target{
@Override
public void v2() {
System.out.println("v2");
}
}
public class test {
public static void main(String[] args) {
adapter a = new adapter();
a.v1();
a.v2();
}
}
对象的适配器:
// 目标类
interface target{
public void v1();
public void v2();
}
// 源
class adaptee{
public void v1(){
System.out.println("v1");
}
}
// 适配器类
class adapter implements target {
private adaptee a;
public adapter(adaptee a){
super();
this.a = a;
}
@Override
public void v1() {
a.v1();
}
@Override
public void v2() {
System.out.println("v2");
}
}
public class test {
public static void main(String[] args) {
adaptee a1 = new adaptee();
adapter a2 = new adapter(a1);
a2.v1();
a2.v2();
}
}
外观模式 Facade Pattern
也叫 面板模式、门面模式
外观主要提供对象的一致对外的接口
中介模式实现的是让对象之间的通信由多对一变为一对一
当你的程序有很多个模块,或者说子系统。
你希望给用户提供一个统一的操作界面类,而不是让用户分别与这些模块交互
子模块
//订单系统
public class OrderSys {
public String getOrderNum(){
System.out.println("获取订单号");
return "123456";
}
}
//支付系统
public class PaymentSys {
private OrderSys orderSys;
public PaymentSys(OrderSys orderSys) {
this.orderSys = orderSys;
}
public BigDecimal getOrderAccount(String orderNum){
System.out.println(String.format("获取%s订单支付金额",orderNum));
return BigDecimal.valueOf(500);
}
}
//物流系统
public class DeliverySys {
public int getDeliveryTime(){
System.out.println("获取配送耗时");
return 30*60;//30分钟
}
}
外观类
public class ReportFacade {
public void generateReport() {
OrderSys orderSys = new OrderSys();
PaymentSys paymentSys = new PaymentSys(orderSys);
DeliverySys deliverySys = new DeliverySys();
final String orderNum = orderSys.getOrderNum();
System.out.println(String.format("\n报表\n--------------------------------------------\n" +
"订单号:%s | 金额:%s元 | 配送耗时:%s分钟",
orderNum,
paymentSys.getOrderAccount(orderNum).toPlainString(),
String.valueOf(deliverySys.getDeliveryTime() / 60))
);
}
}
客户端使用
public class FacadeClient {
public void printReport(){
new ReportFacade().generateReport();
}
}
获取订单号
获取123456订单支付金额
获取配送耗时
报表
--------------------------------------------
订单号:123456 | 金额:500元 | 配送耗时:30分钟
缺点:
子系统的变动可能会引起外观层甚至客户端的改动,违背开闭原则
代理模式 Proxy
你不好意思向你关系不太好朋友帮个忙,这时需要找一个和它关系好的应一个朋友帮忙转达,这个中间朋友就是代理对象。
购买火车票不一定要去火车站买,可以通过12306网站 或 去火车票代售点买
找女朋友、找保姆、找工作 可以通过找中介完成
静态代理 动态代理
王二狗的老板突然在发工资的前一天带着小姨子跑路了,二狗一身房贷,被迫提起劳动仲裁
指派代理律师全权负责二狗的仲裁事宜
诉讼的接口
public interface ILawSuit {
void submit(String proof);//提起诉讼
void defend();//法庭辩护
}
二狗:
public class SecondDogWang implements ILawSuit {
@Override
public void submit(String proof) {
System.out.println(String.format("老板欠薪跑路,证据如下:%s",proof));
}
@Override
public void defend() {
System.out.println(String.format("铁证如山,%s还钱","马旭"));
}
}
代理律师诉讼类,实现ILawSuit接口
public class ProxyLawyer implements ILawSuit {
ILawSuit plaintiff;//持有要代理的那个对象
public ProxyLawyer(ILawSuit plaintiff) {
this.plaintiff=plaintiff;
}
@Override
public void submit(String proof) {
plaintiff.submit(proof);
}
@Override
public void defend() {
plaintiff.defend();
}
}
静态代理工厂类
public class ProxyFactory {
public static ILawSuit getProxy(){
return new ProxyLawyer(new SecondDogWang());
}
}
public static void main(String[] args) {
ProxyFactory.getProxy().submit("工资流水在此");
ProxyFactory.getProxy().defend();
}
老板欠薪跑路,证据如下:工资流水在此
铁证如山,马旭还钱
动态代理类:
牛翠花是二狗的同事,也使用静态代理的话,那么就需要再添加两个类。
一个是牛翠花诉讼类,一个是牛翠花的代理律师类,还的在代理静态工厂中添加一个方法
public interface ILawSuit {
void submit(String proof);//提起诉讼
void defend();//法庭辩护
}
public class CuiHuaNiu implements ILawSuit {
@Override
public void submit(String proof) {
System.out.println(String.format("老板欠薪跑路,证据如下:%s",proof));
}
@Override
public void defend() {
System.out.println(String.format("铁证如山,%s还牛翠花血汗钱","马旭"));
}
}
动态代理类
public class DynProxyLawyer implements InvocationHandler {
private Object target;//被代理的对象
public DynProxyLawyer(Object obj){
this.target=obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("案件进展:"+method.getName());
Object result=method.invoke(target,args); // 执行获取的方法
return result;
}
}
修改静态工厂方法
public class ProxyFactory {
public static Object getDynProxy(Object target) {
InvocationHandler handler = new DynProxyLawyer(target);
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), handler);
}
}
客户端:
public static void main(String[] args) {
ILawSuit proxy= (ILawSuit) ProxyFactory.getDynProxy(new CuiHuaNiu());
proxy.submit("工资流水在此");
proxy.defend();
}
案件进展:submit
老板欠薪跑路,证据如下:工资流水在此
案件进展:defend
铁证如山,马旭还牛翠花血汗钱
简单过程 解析:
config.txt:
类路径
类方法
//读取配置文件
BufferedReader br = new BufferedReader(new FileReader("base68/config.txt"));
String className = br.readLine(); // 类路径
String methodName = br.readLine(); // 类方法
br.close();
//根据类路径 获取类的cLass文件对象
Class<?> aclass = Class.forName(className); // 获取类的class文件
Object o= aClass.newInstance(); // class文件的无参构造方法
Method method = aClass.getMethod(methodName); //获取方法
method.invoke(o); //执行方法
享元模式 Flyweight Pattern
享元模式:运用共享技术 有效支持大量细粒度对象
粒度根据项目模块划分的细致程度区分,一个项目模块(或子模块)分得越多,每个模块(或子模块)越小,负责的工作越细,就说粒度越细,否则为粗粒度
共享技术 → 共享的对象,他是不变的
共享的对象:单车(借车 还车 状态码)
具体的车:摩拜单车(车号 用户 借车 还车)
车工厂:车工场 单车池 给用户提供车
享元 = 单例 + 工厂
优点:
1、极大的减少系统中对象的个数
2、外部状态,外部状态相对独立,不会影响到内部状态 → 享元对象能够在不同的环境被共享
缺点:
1、区分外部状态和内部状态 → 使得应用程序在某种程度上来说更加复杂化了
2、为了使对象可以共享,享元模式需要将享元对象的状态外部化,而读取外部状态使得运行时间变长
使用场景
1、系统有大量相似对象
2、需要缓冲池的场景
HashSet 存储自定义类对象,为什么要重写equals和hashCode方法
https://blog.csdn.net/GaoYan__Ze/article/details/81674079
桥接模式(Bridge Pattern)
抽象部分与它的实现部分分离,使它们都可以独立地变化
问题代码:
public interface ICoffee {
void orderCoffee(int count);
}
原味咖啡类
public class CoffeeOriginal implements ICoffee {
@Override
public void orderCoffee(int count) {
System.out.println(String.format("原味咖啡%d杯",count));
}
}
加糖咖啡类
public class CoffeeWithSugar implements ICoffee {
@Override
public void orderCoffee(int count) {
System.out.println(String.format("加糖咖啡%d杯",count));
}
}
变化:加奶,加蜂蜜 口味,迷你杯,女神杯等等规格
每个需求有a、b、c种情况
要增加的类的个数为(a·b·c)种情况
不能每增加一个需求,就要去加一个类
桥接模式:
实现化部分的接口定义(咖啡口味的维度)
public interface ICoffeeAdditives {
void addSomething();
}
抽象化部分的接口定义(咖啡容量的维度)
//抽象化Abstraction
public abstract class Coffee {
protected ICoffeeAdditives additives;
public Coffee(ICoffeeAdditives additives){
this.additives=additives;
}
public abstract void orderCoffee(int count);
}
//抽象化的修正类
public abstract class RefinedCoffee extends Coffee {
public RefinedCoffee(ICoffeeAdditives additives) {
super(additives);
}
public void checkQuality(){
Random ran=new Random();
System.out.println(String.format("%s 添加%s",additives.getClass().getSimpleName(),ran.nextBoolean()?"太多":"正常"));
}
}
实现 实现化部分(咖啡口味维度)的接口ICoffeeAdditives
//加奶
public class Milk implements ICoffeeAdditives {
@Override
public void addSomething() {
System.out.println("加奶");
}
}
//加糖
public class Sugar implements ICoffeeAdditives {
@Override
public void addSomething() {
System.out.println("加糖");
}
}
实现抽象化部分(咖啡的容量维度)的接口Coffee
//大杯
public class LargeCoffee extends RefinedCoffee {
public LargeCoffee(ICoffeeAdditives additives) {
super(additives);
}
@Override
public void orderCoffee(int count) {
additives.addSomething();
System.out.println(String.format("大杯咖啡%d杯",count));
}
}
//小杯
public class SmallCoffee extends RefinedCoffee {
public SmallCoffee(ICoffeeAdditives additives) {
super(additives);
}
@Override
public void orderCoffee(int count) {
additives.addSomething();
System.out.println(String.format("小杯咖啡%d杯",count));
}
}
//中杯
...
客户端调用
public static void main(String[] args) {
//点两杯加奶的大杯咖啡
RefinedCoffee largeWithMilk=new LargeCoffee(new Milk());
largeWithMilk.orderCoffee(2);
largeWithMilk.checkQuality();
}
加奶
大杯咖啡2杯
Milk 添加太多
组合模式
https://blog.csdn.net/jokeMqc/article/details/121614598
即:文件夹 文件 模式
学校 部门
https://blog.csdn.net/jokeMqc/article/details/121614598
public abstract class OrganizationComponent {
private String name; // 名字
private String des; // 说明
protected void add(OrganizationComponent organizationComponent) {
//默认实现
throw new UnsupportedOperationException();
}
protected void remove(OrganizationComponent organizationComponent) {
//默认实现
throw new UnsupportedOperationException();
}
//构造器
public OrganizationComponent(String name, String des) {
super();
this.name = name;
this.des = des;
}
// get set...
//方法print, 做成抽象的, 子类都需要实现
protected abstract void print();
}
public class Department extends OrganizationComponent {
//没有集合
public Department(String name, String des) {
super(name, des);
// TODO Auto-generated constructor stub
}
//add , remove 就不用写了,因为他是叶子节点
@Override
public String getName() {
// TODO Auto-generated method stub
return super.getName();
}
@Override
public String getDes() {
// TODO Auto-generated method stub
return super.getDes();
}
@Override
protected void print() {
// TODO Auto-generated method stub
System.out.println(getName());
}
}
public class College extends OrganizationComponent {
//List 中 存放的Department
List<OrganizationComponent> organizationComponents = new ArrayList<OrganizationComponent>();
// 构造器
public College(String name, String des) {
super(name, des);
}
// 重写add
@Override
protected void add(OrganizationComponent organizationComponent) {
// TODO Auto-generated method stub
// 将来实际业务中,Colleage 的 add 和 University add 不一定完全一样
organizationComponents.add(organizationComponent);
}
// 重写remove
@Override
protected void remove(OrganizationComponent organizationComponent) {
// TODO Auto-generated method stub
organizationComponents.remove(organizationComponent);
}
@Override
public String getName() {
// TODO Auto-generated method stub
return super.getName();
}
@Override
public String getDes() {
// TODO Auto-generated method stub
return super.getDes();
}
// print方法,就是输出University 包含的学院
@Override
protected void print() {
// TODO Auto-generated method stub
System.out.println("--------------" + getName() + "--------------");
//遍历 organizationComponents
for (OrganizationComponent organizationComponent : organizationComponents) {
organizationComponent.print();
}
}
}
//University 就是 Composite , 可以管理College
public class University extends OrganizationComponent {
List<OrganizationComponent> organizationComponents = new ArrayList<OrganizationComponent>();
// 构造器
public University(String name, String des) {
super(name, des);
// TODO Auto-generated constructor stub
}
// 重写add
@Override
protected void add(OrganizationComponent organizationComponent) {
// TODO Auto-generated method stub
organizationComponents.add(organizationComponent);
}
// 重写remove
@Override
protected void remove(OrganizationComponent organizationComponent) {
// TODO Auto-generated method stub
organizationComponents.remove(organizationComponent);
}
@Override
public String getName() {
// TODO Auto-generated method stub
return super.getName();
}
@Override
public String getDes() {
// TODO Auto-generated method stub
return super.getDes();
}
// print方法,就是输出University 包含的学院
@Override
protected void print() {
// TODO Auto-generated method stub
System.out.println("--------------" + getName() + "--------------");
//遍历 organizationComponents
for (OrganizationComponent organizationComponent : organizationComponents) {
organizationComponent.print();
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
//从大到小创建对象 学校
OrganizationComponent university = new University("清华大学", " 中国顶级大学 ");
//创建 学院
OrganizationComponent computerCollege = new College("计算机学院", " 计算机学院 ");
OrganizationComponent infoEngineercollege = new College("信息工程学院", " 信息工程学院 ");
//创建各个学院下面的系(专业)
computerCollege.add(new Department("软件工程", " 软件工程不错 "));
computerCollege.add(new Department("网络工程", " 网络工程不错 "));
computerCollege.add(new Department("计算机科学与技术", " 计算机科学与技术是老牌的专业 "));
//
infoEngineercollege.add(new Department("通信工程", " 通信工程不好学 "));
infoEngineercollege.add(new Department("信息工程", " 信息工程好学 "));
//将学院加入到 学校
university.add(computerCollege);
university.add(infoEngineercollege);
//university.print();
infoEngineercollege.print();
}
--------------清华大学--------------
--------------计算机学院--------------
软件工程
网络工程
计算机科学与技术
--------------信息工程学院--------------
通信工程
信息工程
装饰模式
不必改变原类和使用继承的情况下,动态地扩展一个对象的功能
它是通过创建一个包装对象,也就是装饰来包裹真实的对象
例子
大杯原味、大杯加糖、大杯加奶;中杯原味、中杯加糖、中杯加奶;小杯原味、小杯加糖、小杯加奶
public interface ICoffee {
void makeCoffee();
}
public class OriginalCoffee implements ICoffee {
@Override
public void makeCoffee() {
System.out.print("原味咖啡 ");
}
}
构建装饰者抽象基类,它要实现与原始对象相同的接口ICoffee,其内部持有一个ICoffee类型的引用,用来接收被装饰的对象:
public abstract class CoffeeDecorator implements ICoffee {
private ICoffee coffee;
public CoffeeDecorator(ICoffee coffee){
this.coffee=coffee;
}
@Override
public void makeCoffee() {
coffee.makeCoffee();
}
}
public class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(ICoffee coffee) {
super(coffee);
}
@Override
public void makeCoffee() {
super.makeCoffee();
addMilk();
}
private void addMilk(){
System.out.print("加奶 ");
}
}
public class SugarDecorator extends CoffeeDecorator {
public SugarDecorator(ICoffee coffee) {
super(coffee);
}
@Override
public void makeCoffee() {
super.makeCoffee();
addSugar();
}
private void addSugar(){
System.out.print("加糖");
}
}
客户端
public static void main(String[] args) {
//原味咖啡
ICoffee coffee=new OriginalCoffee();
coffee.makeCoffee();
System.out.println("");
//加奶的咖啡
coffee=new MilkDecorator(coffee);
coffee.makeCoffee();
System.out.println("");
//先加奶 后加糖的咖啡
coffee=new SugarDecorator(coffee);
coffee.makeCoffee();
}
原味咖啡
原味咖啡 加奶
原味咖啡 加奶 加糖
行为性模式
迭代器模式 Iterator Pattern
顺序访问集合对象的元素,不需要知道集合对象的底层表示
public interface Iterator<E> {
boolean hasNext();
E next();
//java8后加入的default方法
...
}
public interface Iterable<T> {
Iterator<T> iterator();
//java8后加入的default方法
...
}
实现
public class Class implements Iterable<Student> {
private final List<Student> students = new ArrayList<>();
public Class() {
students.add(new Student("王二狗", 28));
students.add(new Student("牛翠花", 20));
students.add(new Student("林蛋大", 29));
}
public boolean addStudent(Student student){
return students.add(student);
}
public boolean removeStudent(Student student){
return students.remove(student);
}
@Override
public Iterator<Student> iterator() {
return new Itr();
}
private class Itr implements Iterator<Student> {
int index = 0;
@Override
public boolean hasNext() {
if (index < students.size()) {
return true;
}
return false;
}
@Override
public Student next() {
Student student = students.get(index);
index++;
return student;
}
}
}
客户端
public class IteratorClient {
public void checkAttendance(){
Class cls= new Class();
System.out.println("--------------开始点名--------------");
Iterator<Student> iterator= cls.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
--------------开始点名--------------
Student{name='王二狗', age=28}
Student{name='牛翠花', age=20}
Student{name='林蛋大', age=29}
责任链模式
一个请求需要被多个对象中的某一个处理,但到底是哪个对象必须在运行时根据条件决定
所有处理器都要实现的接口
public interface BudgetHandler {
//设置下一个处理器,在自己不能处理此请求的情况下,将请求交给下一个处理器
void setNextHandler(BudgetHandler nextHandler);
// 负责处理请求
boolean handle(int amount);
}
实现各种处理器
小组领导类
public class GroupLeader implements BudgetHandler {
private BudgetHandler nextHandler;
@Override
public void setNextHandler(BudgetHandler nextHandler) {
this.nextHandler = nextHandler;
}
@Override
public boolean handle(int amount) {
Objects.requireNonNull(nextHandler);
if(amount<1000){
System.out.println("小钱,批了!");
return true;
}
System.out.println(String.format("%d超出GroupLeader权限,请更高级管理层批复",amount));
return nextHandler.handle(amount);
}
}
经理类:
public class Manager implements BudgetHandler {
private BudgetHandler nextHandler;
@Override
public void setNextHandler(BudgetHandler nextHandler) {
this.nextHandler = nextHandler;
}
@Override
public boolean handle(int amount) {
Objects.requireNonNull(nextHandler);
if(amount<5000){
System.out.println("小于2000块,我这个经理可以决定:同意!");
return true;
}
System.out.println(String.format("%d超出Manager权限,请更高级管理层批复",amount));
return nextHandler.handle(amount);
}
}
首席财务官类
public class CFO implements BudgetHandler {
private BudgetHandler nextHandler;
@Override
public void setNextHandler(BudgetHandler nextHandler) {
this.nextHandler = nextHandler;
}
@Override
public boolean handle(int amount) {
if(amount<50000){
System.out.println("CFO同意,希望你再接再厉,为公司做出更大的贡献。");
return true;
}
if (nextHandler!=null){
return nextHandler.handle(amount);
}
//已经没有更高级的管理层来处理了
System.out.println(String.format("%d太多了,回去好好看看能不能缩减一下",amount));
return false;
}
}
客户端
public class DogWang2Cor {
public void applyBudget() {
GroupLeader leader = new GroupLeader();
Manager manager = new Manager();
CFO cfo = new CFO();
leader.setNextHandler(manager);
manager.setNextHandler(cfo);
System.out.println(String.format("领导您好:由于开发需求,需要购买一台Mac笔记本电脑,预算为%d 望领导批准", 95000));
if (leader.handle(95000)) {
System.out.println("谢谢领导");
} else {
System.out.println("巧妇难为无米之炊,只能划船了...");
}
}
}
领导您好:由于开发需求,需要购买一台Mac笔记本电脑,预算为20000 望领导批准
20000超出GroupLeader权限,请更高级管理层批复
20000超出Manager权限,请更高级管理层批复
CFO同意,希望你再接再厉,为公司做出更大的贡献。
谢谢领导
类多了,如果组链时候不合理,可能导致请求得不到执行,
还有可能将链变成一个环,请求在里面循环,永远都完不了
观察者模式
例子1
何时使用:一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知
当一个对象被修改时,自动通知依赖它的对象
https://www.runoob.com/design-pattern/observer-pattern.html
例子:
珠宝商有黄金运输,保镖 强盗 警察要观察
// 观察者的接口
interface watcher{
public void update();
}
// 观察者的类
// 保镖
class security implements watcher{
@Override
public void update() {
System.out.println("保镖在保护黄金");
}
}
// 强盗
class thief implements watcher{
@Override
public void update() {
System.out.println("强盗想抢劫这批黄金");
}
}
// 警察
class police implements watcher{
@Override
public void update() {
System.out.println("警察在保护这批黄金");
}
}
// 被观察者的接口
interface watched{
public void add_watcher(watcher w);
public void remove_watcher(watcher w);
public void notitf_watcher();
}
// 被观察者的类
// 黄金是被观察者
class transport implements watched{
private List<watcher> list = new ArrayList<watcher>();
@Override
public void add_watcher(watcher w) {
list.add(w);
}
@Override
public void remove_watcher(watcher w) {
list.remove(w);
}
@Override
public void notitf_watcher() {
for (watcher w:list)
w.update();
}
}
public class test {
public static void main(String[] args) {
transport tr = new transport();
police p = new police();
security s = new security();
thief th = new thief();
tr.add_watcher(p);
tr.add_watcher(s);
tr.add_watcher(th);
tr.notitf_watcher();
}
}
例子2
状态模式
优化 if…else,允许对象在内部状态发生改变时改变它的行为
push:
blue → green → black → red → blue
pull:
blue → red → black → green → blue
一般操作就有8个 if-else判断,麻烦
优化后:
abstract class state{
public abstract void handpush(Context c);
public abstract void handpull(Context c);
public abstract Color getcolor();
}
// 状态管理器
class Context{
private state s = null;
public void set_state(state s){
this.s = s;
}
public void push() {
s.handpush(this);
}
public void pull(){
s.handpull(this);
}
}
class blue extends state{
@Override
public void handpush(Context c) {
System.out.println("变为绿色");
c.set_state(new green());
}
@Override
public void handpull(Context c) {
System.out.println("变为红色");
c.set_state(new red());
}
@Override
public Color getcolor() {
return Color.blue;
}
}
class green extends state{
@Override
public void handpush(Context c) {
System.out.println("变为黑色");
c.set_state(new black());
}
@Override
public void handpull(Context c) {
System.out.println("变为蓝色");
c.set_state(new blue());
}
@Override
public Color getcolor() {
return Color.green;
}
}
class black extends state{
@Override
public void handpush(Context c) {
System.out.println("变为红色");
c.set_state(new red());
}
@Override
public void handpull(Context c) {
System.out.println("变为绿色");
c.set_state(new green());
}
@Override
public Color getcolor() {
return Color.black;
}
}
class red extends state{
@Override
public void handpush(Context c) {
System.out.println("变为蓝色");
c.set_state(new blue());
}
@Override
public void handpull(Context c) {
System.out.println("变为黑色");
c.set_state(new black());
}
@Override
public Color getcolor() {
return Color.red;
}
}
public class test {
public static void main(String[] args) {
blue blue = new blue();
green green = new green();
black black = new black();
red red = new red();
Context c = new Context();
blue.handpush(c);
red.handpull(c);
}
}
策略模式
策略模式定义了一系列的算法,并将每一个算法封装起来,使他们可以相互替换。
demo1
消灭大量 if
https://blog.csdn.net/qq_37949192/article/details/116993087
https://blog.csdn.net/guorui_java/article/details/121304941
demo2:
public interface Strategy {
int doOperation(int num1, int num2);
}
public class OperationAdd implements Strategy {
@Override
public int doOperation(int num1, int num2) {
return num1 + num2;
}
}
public class OperationMultiply implements Strategy {
@Override
public int doOperation(int num1, int num2) {
return num1 * num2;
}
}
public class OperationSubtract implements Strategy {
@Override
public int doOperation(int num1, int num2) {
return num1 - num2;
}
}
方向1
public class Context {
private Strategy strategy;
public void setContextStrategy(Strategy strategy) {
this.strategy = strategy;
}
public int executeStrategy(int num1, int num2) {
return strategy.doOperation(num1, num2);
}
}
public class StrategyPatternDemo {
public static void main(String[] args) {
Context context = new Context();
context.setContextStrategy(new OperationAdd());
System.out.println("10 + 5 =" + context.executeStrategy(10, 5));
context.setContextStrategy(new OperationSubtract());
System.out.println("10 - 5 = " + context.executeStrategy(10, 5));
context.setContextStrategy(new OperationMultiply());
System.out.println("10 * 5 = " + context.executeStrategy(10, 5));
}
}
方向2
public class StrategyDemo {
private static final Map<String, Strategy> strategies = new HashMap<>();
static {
strategies.put("add", new OperationAdd());
strategies.put("multiply", new OperationMultiply());
strategies.put("subtract", new OperationSubtract());
}
public static Strategy getStrategy(String type) {
if (type == null || type.isEmpty()) {
throw new IllegalArgumentException("type should not be empty.");
}
return strategies.get(type);
}
}
public class StrategyPatternDemo2 {
public static void main(String[] args) {
// 运行时动态确定,根据配置文件的配置决定使用哪种策略
Strategy strategy = null;
strategy = StrategyDemo.getStrategy("add"); //获取策略类
System.out.println("10 + 5 =" + strategy.doOperation(10, 5)); //调用策略接口
strategy = StrategyDemo.getStrategy("multiply"); //获取策略类
System.out.println("10 * 5 =" + strategy.doOperation(10, 5)); //调用策略接口
strategy = StrategyDemo.getStrategy("subtract"); //获取策略类
System.out.println("10 - 5 =" + strategy.doOperation(10, 5)); //调用策略接口
Example example = new Example();
example.calculate(10, 5, "add");
}
}
策略 vs 状态
https://www.runoob.com/w3cnote/state-vs-strategy.html
3个设计原则:
找出应用中可能需要变化之处,把他们独立出来
针对接口编程,而不是针对实现
多用组合,少用继承
状态模式策略模式很相似,也是将类的 “状态” 封装了起来,在执行动作时进行自动的转换,从而实现,类在不同状态下的同一动作显示出不同结果
它与策略模式的区别在于,这种转换是"自动","无意识"的
状态:不同状态的切换可由子类实现
策略:算法簇之间完全解耦
状态模式:
A状态,过渡到B状态
所以状态与状态之间是互相依赖的,耦合度是比较紧的
策略:策略与策略之间,相互独立
模板方法模式
在一个方法中定义一个算法的骨架,而将一些步骤的实现延迟到子类中,使得子类可以在不改变一个算法的结构前提下即可重定义该算法的某些特定步骤
public abstract class LivePlay {
//模板方法
public final void seeLivePlay() {
login();
openRoom();
startAudioAndVideoStream();
pushVideoStream();
stopAudioAndVideoStream();
closeRoom();
}
//实体方法,这个方法实现通用的业务逻辑
private void login() {
System.out.println("用户登录");
}
/*抽象方法*/
//打开房间
public abstract void openRoom();
//打开音视频流
public abstract void startAudioAndVideoStream();
//关闭音视频流
public abstract void stopAudioAndVideoStream();
//关闭房间
public abstract void closeRoom();
/*钩子方法,可以被需要的子类overwrite*/
//旁路推流,可以通过视频链接在浏览器中查看视频
public void pushVideoStream() {
}
}
//腾讯直播类
public class TencentLivePlay extends LivePlay {
@Override
public void openRoom() {
System.out.println("腾讯打开房间");
}
@Override
public void startAudioAndVideoStream() {
System.out.println("腾讯打开音视频流");
}
@Override
public void stopAudioAndVideoStream() {
System.out.println("腾讯关闭音视频流");
}
@Override
public void closeRoom() {
System.out.println("腾讯关闭房间");
}
//覆写钩子方法,提供旁路推流功能
@Override
public void pushVideoStream() {
super.pushVideoStream();
System.out.println("腾讯进行旁路推流");
}
}
//金山直播类
public class JinShanLivePlay extends LivePlay {
@Override
public void openRoom() {
System.out.println("金山打开房间");
}
@Override
public void startAudioAndVideoStream() {
System.out.println("金山打开音视频流");
}
@Override
public void stopAudioAndVideoStream() {
System.out.println("金山关闭音视频流");
}
@Override
public void closeRoom() {
System.out.println("金山关闭房间");
}
}
客户端
public static void main(String[] args) {
//此处省略若干代码
...
LivePlay tencentLive=new TencentLivePlay();
tencentLive.seeLivePlay();
System.out.println("");
LivePlay jinShanLive=new JinShanLivePlay();
jinShanLive.seeLivePlay();
}
备忘录模式
打游戏 保存上次游戏状态记录
public class GameProgressMemento {
private int score;
public GameProgressMemento(int score) {
this.score = score;
}
public int getScore() {
return score;
}
}
public class GameOriginator {
private int currentScore;
//将需要保存的状态分装在Memento里对外提供
public GameProgressMemento saveProcess() {
return new GameProgressMemento(currentScore);
}
//通过从外部接收的Memento恢复状态
public void restoreProcess(GameProgressMemento memento) {
currentScore = memento.getScore();
}
//对内部状态的使用
public void playGame() {
System.out.println("------------------开始游戏------------------");
System.out.println("当前分数为:"+ currentScore);
System.out.println("杀死一个小怪物得1分");
currentScore++;
System.out.println(String.format("总分为:%d", currentScore));
}
public void exitGame(){
System.out.println("退出游戏");
currentScore=0;
System.out.println("-----------------退出游戏-------------------");
}
}
public class GameCareTaker {
private List<GameProgressMemento> memento= new ArrayList<>();
public void saveMemento(GameProgressMemento memento) {
this.memento.add(memento);
}
public GameProgressMemento getMemento(int index) {
return this.memento.get(index);
}
}
客户端使用:
public class MementoClient {
public void replayGame() {
GameOriginator originator = new GameOriginator();
GameCareTaker careTaker = new GameCareTaker();
//玩游戏
originator.playGame();
//保存进度
careTaker.saveMemento(originator.saveProcess());
//退出游戏
originator.exitGame();
//重新打开游戏,恢复进度
originator.restoreProcess(careTaker.getMemento(0));
originator.playGame();
}
}
------------------开始游戏------------------
当前分数为:0
杀死一个小怪物得1分
总分为:1
退出游戏
-----------------退出游戏-------------------
------------------开始游戏------------------
当前分数为:1
杀死一个小怪物得1分
总分为:2
访问者模式
https://www.jianshu.com/p/1f1049d0a0f4
// 员工基类
public abstract class Staff {
public String name;
public int kpi;// 员工KPI
public Staff(String name) {
this.name = name;
kpi = new Random().nextInt(10);
}
// 核心方法,接受Visitor的访问
public abstract void accept(Visitor visitor);
}
// 工程师
public class Engineer extends Staff {
public Engineer(String name) {
super(name);
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
// 工程师一年的代码数量
public int getCodeLines() {
return new Random().nextInt(10 * 10000);
}
}
// 经理
public class Manager extends Staff {
public Manager(String name) {
super(name);
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
// 一年做的产品数量
public int getProducts() {
return new Random().nextInt(10);
}
}
public interface Visitor {
// 访问工程师类型
void visit(Engineer engineer);
// 访问经理类型
void visit(Manager manager);
}
// 员工业务报表类
public class BusinessReport {
private List<Staff> mStaffs = new LinkedList<>();
public BusinessReport() {
mStaffs.add(new Manager("经理-A"));
mStaffs.add(new Engineer("工程师-A"));
mStaffs.add(new Engineer("工程师-B"));
mStaffs.add(new Engineer("工程师-C"));
mStaffs.add(new Manager("经理-B"));
mStaffs.add(new Engineer("工程师-D"));
}
/**
* 为访问者展示报表
* @param visitor 公司高层,如CEO、CTO
*/
public void showReport(Visitor visitor) {
for (Staff staff : mStaffs) {
staff.accept(visitor);
}
}
}
访问者
// CEO访问者
public class CEOVisitor implements Visitor {
@Override
public void visit(Engineer engineer) {
System.out.println("工程师: " + engineer.name + ", KPI: " + engineer.kpi);
}
@Override
public void visit(Manager manager) {
System.out.println("经理: " + manager.name + ", KPI: " + manager.kpi +
", 新产品数量: " + manager.getProducts());
}
}
public class CTOVisitor implements Visitor {
@Override
public void visit(Engineer engineer) {
System.out.println("工程师: " + engineer.name + ", 代码行数: " + engineer.getCodeLines());
}
@Override
public void visit(Manager manager) {
System.out.println("经理: " + manager.name + ", 产品数量: " + manager.getProducts());
}
}
错误的访问者:
if else 难以扩展
public class ReportUtil {
public void visit(Staff staff) {
if (staff instanceof Manager) {
Manager manager = (Manager) staff;
System.out.println("经理: " + manager.name + ", KPI: " + manager.kpi +
", 新产品数量: " + manager.getProducts());
} else if (staff instanceof Engineer) {
Engineer engineer = (Engineer) staff;
System.out.println("工程师: " + engineer.name + ", KPI: " + engineer.kpi);
}
}
}
客户端:
public class Client {
public static void main(String[] args) {
// 构建报表
BusinessReport report = new BusinessReport();
System.out.println("=========== CEO看报表 ===========");
report.showReport(new CEOVisitor());
System.out.println("=========== CTO看报表 ===========");
report.showReport(new CTOVisitor());
}
}
=========== CEO看报表 ===========
经理: 经理-A, KPI: 9, 新产品数量: 0
工程师: 工程师-A, KPI: 6
工程师: 工程师-B, KPI: 6
工程师: 工程师-C, KPI: 8
经理: 经理-B, KPI: 2, 新产品数量: 6
工程师: 工程师-D, KPI: 6
=========== CTO看报表 ===========
经理: 经理-A, 产品数量: 3
工程师: 工程师-A, 代码行数: 62558
工程师: 工程师-B, 代码行数: 92965
工程师: 工程师-C, 代码行数: 58839
经理: 经理-B, 产品数量: 6
工程师: 工程师-D, 代码行数: 53125
中介者模式
外观主要提供对象的一致对外的接口
中介模式实现的是让对象之间的通信由多对一变为一对一
房东 中介 租客
public abstract class Mediator {
//申明一个联络方法
public abstract void constact(String message,Person person);
}
public abstract class Person {
protected String name;
protected Mediator mediator;
Person(String name,Mediator mediator){
this.name = name;
this.mediator = mediator;
}
}
房东
public class HouseOwner extends Person{
HouseOwner(String name, Mediator mediator) {
super(name, mediator);
}
/**
* @desc 与中介者联系
* @param message
* @return void
*/
public void constact(String message){
mediator.constact(message, this);
}
/**
* @desc 获取信息
* @param message
* @return void
*/
public void getMessage(String message){
System.out.println("房主:" + name +",获得信息:" + message);
}
}
租客
public class Tenant extends Person{
Tenant(String name, Mediator mediator) {
super(name, mediator);
}
/**
* @desc 与中介者联系
* @param message
* @return void
*/
public void constact(String message){
mediator.constact(message, this);
}
/**
* @desc 获取信息
* @param message
* @return void
*/
public void getMessage(String message){
System.out.println("租房者:" + name +",获得信息:" + message);
}
}
中介
public class MediatorStructure extends Mediator{
//首先中介结构必须知道所有房主和租房者的信息
private HouseOwner houseOwner;
private Tenant tenant;
public HouseOwner getHouseOwner() {
return houseOwner;
}
public void setHouseOwner(HouseOwner houseOwner) {
this.houseOwner = houseOwner;
}
public Tenant getTenant() {
return tenant;
}
public void setTenant(Tenant tenant) {
this.tenant = tenant;
}
public void constact(String message, Person person) {
if(person == houseOwner){ //如果是房主,则租客获得信息
tenant.getMessage(message);
}
else{ //房主获得信息
houseOwner.getMessage(message);
}
}
}
客户端
public class Client {
public static void main(String[] args) {
//一个房主、一个租房者、一个中介机构
MediatorStructure mediator = new MediatorStructure();
//房主和租房者只需要知道中介机构即可
HouseOwner houseOwner = new HouseOwner("张三", mediator);
Tenant tenant = new Tenant("李四", mediator);
//中介结构要知道房主和租房者
mediator.setHouseOwner(houseOwner);
mediator.setTenant(tenant);
tenant.constact("听说你那里有三室的房主出租.....");
houseOwner.constact("是的!请问你需要租吗?");
}
}
题目
设计模式的两大主题 4
1 系统的维护与开发
2 对象组合与类的继承
3 系统架构与系统开发
4 系统复用与系统扩展
当我们想创建一个具体的对象而又不希望指定具体的类时,可以使用()模式 1
创建型
结构型
行为型
以上都可以
设计模式的一个优点是 2
程序易于理解
适应需求变化
减少代码量
简化软件系统设计
定义一系列算法,把它们一个个封装起来,并使它们可相互替换,这是对哪种模式的描述 3
观察者模式
桥接模式
策略模式
适配器模式
以下哪条不属于SOLID原则 3
依赖倒置
里氏替换原则
最小知识原则
开闭原则
属于创建型模式的有 2 3
适配器模式
单例模式
工厂模式
观察者模式
将一个类的接口转换成客户希望的另一个接口。是对哪种模式的描述 2
桥接模式
适配器模式
中介者模式
策略模式
()定义了一个高层接口,这个接口使得这一子系统更加容易使用 4
Adapter(适配器)模式
Bridge(桥接)模式
Strategy(策略)模式
Facade(外观)模式