目录
工厂模式(Factory)
百度搜索一下可以看到是:
简单来讲就是将原本的直接new变成了由一个专门的工厂类来new。
工厂模式为什么要替代new的方式初始化对象呢?
案例给你答案:
需求:一个披萨制作的项目,要求该项目易于扩展维护;
1、能够生产出美式披萨、中式披萨...
2、披萨制作过程包含原材料准备、烘培、切割、打包
3、可生成披萨订单
使用工厂模式前:
AmericaPizza(美式披萨)
package com.penghua.factory;
/**
* 美式披萨
*/
class AmericaPizza implements Pizza {
public AmericaPizza() {
this.pre();
this.bake();
this.cut();
this.box();
}
@Override
public void pre() {
System.out.println("美式 披萨材料准备...");
}
@Override
public void bake() {
System.out.println("美式 披萨烘培...");
}
@Override
public void cut() {
System.out.println("美式 披萨的切片...");
}
@Override
public void box() {
System.out.println("美式 披萨包装盒包装");
}
}
ChinesePizza(中式披萨)
package com.penghua.factory;
/**
* 中式披萨
*/
class ChinesePizza implements Pizza {
public ChinesePizza() {
this.pre();
this.bake();
this.cut();
this.box();
}
@Override
public void pre() {
System.out.println("中式披萨材料准备...");
}
@Override
public void bake() {
System.out.println("中式披萨烘培...");
}
@Override
public void cut() {
System.out.println("中式披萨的切片...");
}
@Override
public void box() {
System.out.println("中式披萨包装盒包装");
}
}
Client(事件)
package com.penghua.factory;
public class Client {
public static void main(String[] args) {
Pizza chinaPizza = PizzaFactory.createPizza(1);
System.out.println("=============================");
Pizza americaPizza = PizzaFactory.createPizza(2);
System.out.println("=============================");
Pizza japanPizza = PizzaFactory.createPizza(3);
}
}
JapanPizza(日式披萨)
package com.penghua.factory;
/**
* 日式披萨
*/
class JapanPizza implements Pizza {
public JapanPizza() {
this.pre();
this.bake();
this.cut();
this.box();
}
@Override
public void pre() {
System.out.println("日式 披萨材料准备...");
}
@Override
public void bake() {
System.out.println("日式 披萨烘培...");
}
@Override
public void cut() {
System.out.println("日式 披萨的切片...");
}
@Override
public void box() {
System.out.println("日式 披萨包装盒包装");
}
}
Pizza(父类:披萨)
package com.penghua.factory;
/**
* 披萨(父类)
*/
public interface Pizza {
void pre();
void bake();
void cut();
void box();
}
PizzaFactory(披萨工厂类)
package com.penghua.factory;
/**
* 披萨工厂类
*/
public class PizzaFactory {
public static Pizza createPizza(int no){
switch (no){
case 1:
return new ChinesePizza();
case 2:
return new AmericaPizza();
case 3:
return new JapanPizza();
}
return null;
}
}
虽然这样也有工程类,但是实际上披萨的制作在对应的披萨的构造方法时使用,这样会导致如果有子类继承该方法时也会执行操作。通俗易懂的来说:你要吃菜,那么你要先买菜、洗菜、做菜然后才能吃。但是你去别人店里同样是吃菜就不需要那么麻烦,就不需要那么多步骤,老板直接做菜就行。但是如果你继承的话就会把不需要的步骤也执行了。
下面是工厂模式:
AmericaPizza(美式披萨)
package com.penghua.factory;
/**
* 美式披萨
*/
class AmericaPizza implements Pizza {
@Override
public void pre() {
System.out.println("美式 披萨材料准备...");
}
@Override
public void bake() {
System.out.println("美式 披萨烘培...");
}
@Override
public void cut() {
System.out.println("美式 披萨的切片...");
}
@Override
public void box() {
System.out.println("美式 披萨包装盒包装");
}
}
ChinesePizza(中式披萨)
package com.penghua.factory;
/**
* 中式披萨
*/
class ChinesePizza implements Pizza {
@Override
public void pre() {
System.out.println("中式披萨材料准备...");
}
@Override
public void bake() {
System.out.println("中式披萨烘培...");
}
@Override
public void cut() {
System.out.println("中式披萨的切片...");
}
@Override
public void box() {
System.out.println("中式披萨包装盒包装");
}
}
Client
package com.penghua.factory;
public class Client {
public static void main(String[] args) {
Pizza chinaPizza = PizzaFactory.createPizza(1);
System.out.println("=============================");
Pizza americaPizza = PizzaFactory.createPizza(2);
System.out.println("=============================");
Pizza japanPizza = PizzaFactory.createPizza(3);
System.out.println("=============================");
Pizza otherPizza = PizzaFactory.createPizza(4);
}
}
JapanPizza(日式披萨)
package com.penghua.factory;
class JapanPizza implements Pizza {
@Override
public void pre() {
System.out.println("日式 披萨材料准备...");
}
@Override
public void bake() {
System.out.println("日式 披萨烘培...");
}
@Override
public void cut() {
System.out.println("日式 披萨的切片...");
}
@Override
public void box() {
System.out.println("日式 披萨包装盒包装");
}
}
Pizza(父类:披萨)
package com.penghua.factory;
public interface Pizza {
void pre();
void bake();
void cut();
void box();
}
PizzaFactory(披萨工厂类)
package com.penghua.factory;
public class PizzaFactory {
public static Pizza createPizza(int no){
Pizza pizza = null;
switch (no){
case 1:
pizza = new ChinesePizza();
break;
case 2:
pizza = new AmericaPizza();
break;
case 3:
pizza = new JapanPizza();
break;
}
if (pizza == null){
System.out.println("没有此披萨订购服务");
}else {
pizza.pre();
pizza.bake();
pizza.cut();
pizza.box();
}
return pizza;
}
}
代码其实差不多,不过把数据的初始化放到了工厂类中,不在各种披萨的构造方法了,这样的好处是可以保证后续(子类继承父类,不同的方法也不会影响),可以快速调整。
目的在于:实例化与初始化数据的解藕
前后的代码对比:
前者:将对象初始化的工作交给了对象的构造函数完成。
后者:将初始化的过程交给了工厂类完成。
这么做的好处在于解耦自身对象实例化和对象初始化动作,还有一个因素在于构造函数的初始化会影响到子类
注意:将对象的初始化交给工厂类,构造函数初始化会影响到子类,藕和度过高
Spring中的javabean是什么时候初始化的?
什么时候有值取决于bean的存在方式。
如果是单例模式那么在初始化spring上下文容器时就默认初始化了
如果是多列模式那么要在使用该对象时才会初始化
反正要初始化一次,干脆把所有的初始化操作放到监听器里面去,提高系统应用的性能
多例本身会耗性能,那么就尽可能在使用的时候再去创造对象
Bean的生命周期
单例对象:
出生:当容器创建时对象出生
活着:只要容器还在,对象一直活着
死亡:容器销毁,对象消亡
总结:单例对象的生命周期和容器相同
多例对象:
出生:当我们使用对象时Spring框架为我们创建
活着:对象只要是在使用过程中就一直活着
死亡:当对象长时间不用,且没有别的对象引用时,由Java的垃圾回收器回收
结构性模式之适配器模式(Adapter):
Adapter 模式最大的作用还是将原本不兼容的接口融合在一起工作
其中相关的术语:
source:待适配的类/对象/接口
Adapter:适配器
destination:适配后可用的类/对象/接口
举个例子:要让手机能够使用220V的交流电;注意,手机只接受5.5V的电压。
这个时候我们就会用到手机充电器来充电。这时他们的角色分配就是:
source Power220V===》220V的电源
Adapter PowerAdapt===》电源适配器(手机充电器)
Destination Power5V===》5V的电源
适配器之间也不是完全一样,有自己的分类:
类适配器模式: Adapter 类,通过继承 source 类,实现 Destination 类接口,完成 source->Destination 的适配。
对象适配器模式: 将 Adapter 类作修改,不是继承 source 类,而是持有 source 类的实例,以解决兼容性的问题。 即:持有 source 类,实现 Destination 类接口,完成source->Destination 的适配。
接口适配器模式: 当不需要全部实现接口提供的方法时,可先设计一个抽象类实现接口,并为该接口中每个方法提供一个默认实现(空方法),那么该抽象类的子类可有选择地覆盖父类的某些方法来实现需求 适用于一个接口不想使用其所有的方法的情况。
适配器模式分类三种体现形式思想都大同小异,这里就只介绍最常用的 对象适配器模式;
案例代码如下:
package com.penghua.Adapter;
public class Client {
public static void main(String[] args) {
Phone phone = new Phone();
// 已知有一个220V的电源,要用它给手机进行充电,我们只能将220V的电源进行处理后才能给手机充上电
// 还一种方案:新增5V的一个Voltage5V,Voltage的电压可以被手机使用
// 但是这违背现实生活现象,现实生活中只有220V的电源,其他的电源都是通过适配得来的
phone.charge(new Voltage220V());
}
}
package com.penghua.Adapter;
public class Phone {
// 充电
public void charge(Voltage220V voltage220V){
double voltage = voltage220V.getVoltage() / 40;
System.out.println("最终手机充电所用电压:" + voltage + "V");
}
}
package com.penghua.Adapter;
/**
* 200v的电压
*/
public class Voltage220V {
private double voltage;
public Voltage220V() {
this.voltage = 220;
}
public double getVoltage() {
return voltage;
}
public void setVoltage(double voltage) {
this.voltage = voltage;
}
}
使用适配器后:
package com.penghua.Adapter;
public class Client {
public static void main(String[] args) {
Phone phone = new Phone();
// 已知有一个220V的电源,要用它给手机进行充电,我们只能将220V的电源进行处理后才能给手机充上电
// VoltageAdapter适配器对Voltage220V这个不能直接使用的电源适配后就可以使用了
phone.charge(new VoltageAdapter(new Voltage220V()));
}
}
package com.penghua.Adapter;
public class Phone {
// 充电
public void charge(Voltage5V voltage5V){
double voltage = voltage5V.getVoltage();
System.out.println("最终手机充电所用电压:" + voltage + "V");
}
}
package com.penghua.Adapter;
/**
* 目标接口
*/
interface Voltage5V{
double getVoltage();
}
package com.penghua.Adapter;
/**
* 220V的电压
*/
public class Voltage220V {
private double voltage;
public Voltage220V() {
this.voltage = 220;
}
public double getVoltage() {
return voltage;
}
public void setVoltage(double voltage) {
this.voltage = voltage;
}
}
package com.penghua.Adapter;
import com.penghua.Adapter.myAdapter.Voltage220V;
/**
* 适配器:里面封装了source源到destination目标的过程
*/
class VoltageAdapter implements Voltage5V {
private Voltage220V voltage220V;
public VoltageAdapter(Voltage220V voltage220V) {
this.voltage220V = voltage220V;
}
public VoltageAdapter(com.penghua.Adapter.Voltage220V voltage220V) {
}
@Override
public double getVoltage() {
return voltage220V.getVoltage() / 40;
}
}
桥接模式(Bridge):
技术术语:Bridge(桥接)
Abstraction(抽象类)
concrete:具体的
概念:桥接模式是将抽象部分与它的实现部分分离,使它们都可以独立地变化
案例
需求:手机(型号 + 品牌)操作问题;
完成手机各品牌各型号的项目设计;
列如:折叠式的华为、小米、Vivo,直立式的华为、小米、Vivo,旋转式的、滑盖的...
要求该项目设计易于扩展
首先我们们最容易想到的方案应该如下:
上图是常见的需求设计方案,非常不便于维护,手机的型号与品牌耦合度太高,当要新增滑盖(Slide)式的手机时,对应的品牌手机也要新增;
接下来我们来看看桥接模式是如何设计的?
桥接模式将分为两个模块,抽象部分(款式)和实现部分(品牌),抽象类(款式)中定义啦一个实现类(品牌),如Folded继承拉这个抽象类,并添加有参(Implement 品牌)的构造方法,这样品牌就不会受限制
代码:
public abstract class Abstraction {
protected Implementor implementor;
public abstract void call();
}
class Folded extends Abstraction {
private String name = "折叠式";
Folded(Implementor implementor) {
this.implementor = implementor;
}
@Override
public void call() {
System.out.println(this.implementor.getName() + this.name + "正在通话中");
}
}
class Upright extends Abstraction {
private String name = "直立式";
Upright(Implementor implementor) {
this.implementor = implementor;
}
@Override
public void call() {
System.out.println(this.implementor.getName() + this.name + "正在通话中");
}
}
class Slide extends Abstraction {
private String name = "滑盖式";
Slide(Implementor implementor) {
this.implementor = implementor;
}
@Override
public void call() {
System.out.println(this.implementor.getName() + this.name + "正在通话中");
}
}
package com.javaxl.design.bridge;
/**
* @author 暗夜小白白
* @site https://blog.youkuaiyun.com/qq_65975514?type=blog
* @company
* @create 2022年4月19日03:50:04
* 手机品牌
*/
public interface Implementor {
String getName();
}
class HW implements Implementor{
private String name = "华为";
@Override
public String getName() {
return name;
}
}
class Mi implements Implementor{
private String name = "小米";
@Override
public String getName() {
return name;
}
}
class Vivo implements Implementor{
private String name = "Vivo";
@Override
public String getName() {
return name;
}
}
public class Client {
public static void main(String[] args) {
Folded folded = new Folded(new HW());
folded.call();
Upright upright = new Upright(new Mi());
upright.call();
Slide slide = new Slide(new Vivo());
slide.call();
}
}