首先,我们先要了解结构型设计模式都包括哪些:适配器模式(Adapter)、桥接模式(Bridge)、过滤器模式(Filter)、组合模式(Composite)、装饰器模式(Decorator/Wrapper)、外观模式(Facade)、享元模式(Flyweight)、代理模式(Proxy)。
结构型模型主要关注怎样组合对象或者类,所以结构型模式又分为类结构模式(类的组合,继承)和对象结构模式(类与对象的组合,关联关系)。又因为合成复用原则告诉我们,要尽量使用关联关系代替继承关系,所以结构模型大多数都是对象结构模型。

//播放器接口
public interface Player {
String play();
}
//翻译器接口
public interface Translator {
String translate(String content);
}
//播放器实现
public class MoviePlayer implements Player {
@Override
public String play() {
System.out.println("正在播放:java从入门到精通");
String content = "你好";
System.out.println(content);
return content;
}
}
//转换器实现
public class Zh_JPTranslator implements Translator{
@Override
public String translate(String content) {
if("你好".equals(content)){
return "空尼几哇";
}
if ("什么".equals(content)){
return "纳尼";
}
return "*******";
}
}
//播放器适配器
public class JPMoviePlayerAdapter implements Player {
//组合的方式
private Translator translator = new Zh_JPTranslator();
private Player target;//被适配对象
public JPMoviePlayerAdapter(Player target){
this.target = target;
}
@Override
public String play() {
String play = target.play();
//转换字幕
String translate = translator.translate(play);
System.out.println("日文:"+translate);
return play;
}
}

定义:将抽象与实现解耦,使两者都可以独立变化(真正引起类变化的维度抽取出来),桥接将继承转为关联,降低类之间的耦合度,减少代码量。
举个栗子:有两种手机,拍照手机和性能手机,两种手机在线上和线下的价格都不同,考虑这个类里边的一些东西会扩展很多,就应该把这个东西分离出来。

代码示例:
/**
* 1、抽象手机类
* 手机有各种销售渠道价格都不一样
*/
public abstract class AbstractPhone {
//【真正会引起此类变化的一个维度直接抽取出来,通过组合的方式接起来】
AbstractSale sale; //分离渠道【桥接的关注点】
//当前手机的描述
abstract String getPhone();
public void setSale(AbstractSale sale) {
this.sale = sale;
}
}
/**
* 抽象销售渠道
*/
public abstract class AbstractSale {
private String type;
private Integer price;
public AbstractSale(String type,Integer price){
this.type = type;
this.price = price;
}
String getSaleInfo(){
return "渠道:"+type+"==>"+"价格:"+price;
}
}
//哪种手机,根据手机种类实现......多个
public class PhotoPhone extends AbstractPhone{
@Override
String getPhone() {
return "PhotoPhone:"+sale.getSaleInfo();
}
}
/**
* 线上渠道,根据渠道实现......多个
*/
public class OnlineSale extends AbstractSale{
public OnlineSale(String type, Integer price) {
super(type, price);
}
}
//TestClass
public class MainTest {
public static void main(String[] args) {
//拍照手机的线上渠道
PhotoPhone iPhone = new PhotoPhone();
iPhone.setSale(new OnlineSale("线上",2599));
String phone = iPhone.getPhone();
System.out.println(phone);
}
}

//附一个网上很常见的例子,给图像增加颜色
//抽象的图像
public interface Shape {
void draw();
}
//具体的图像:圆......可以多个,这里只示例一个
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Shape: Circle");
}
}
//抽象的装饰类
public abstract class ShapeDecorator implements Shape {
protected Shape decoratedShape;
public ShapeDecorator(Shape decoratedShape){
this.decoratedShape = decoratedShape;
}
public void draw(){
decoratedShape.draw();
}
}
//具体的装饰类
public class RedShapeDecorator extends ShapeDecorator {
public RedShapeDecorator(Shape decoratedShape) {
super(decoratedShape);
}
@Override
public void draw() {
decoratedShape.draw();
setRedBorder(decoratedShape);
}
private void setRedBorder(Shape decoratedShape){
System.out.println("Border Color: Red");
}
}
定义:给某一个对象提供一个代理,并由代理对象控制对原对象的引用。
代理模式又分为静态代理和动态代理,静态代理和装饰器十分相似,所以大家经常认为装饰器是代理的一种。
下面来看一下动态代理

//一个抖音直播例子
//首先,来两个抽象接口,因为JDK要求被代理对象必须有接口
//抽象的跳舞接口
public interface DanceTikTok {
void dance();
}
//抽像的卖货接口
public interface SellTikTok {
void sell();
}
//实现这两个接口
public class MyTikTok implements DanceTikTok,SellTikTok {
@Override
public void dance() {
System.out.println("跳个舞......");
}
@Override
public void sell() {
System.out.println("3,2,1 上车......");
}
}
//动态代理核心类,万能代理类
public class JdkTiktokProxy<T> implements InvocationHandler {
private T target;
//接受被代理对象
JdkTiktokProxy(T target){
this.target = target;
}
//获取被代理对象的 代理对象
public static<T> T getProxy(T t) {
/**
* ClassLoader loader, 当前被代理对象的类加载器
* Class>[] interfaces, 当前被代理对象所实现的所有接口
* InvocationHandler h,
* 当前被代理对象执行目标方法的时候我们使用h可以定义拦截增强方法
*/
Object o = Proxy.newProxyInstance(
t.getClass().getClassLoader(),
t.getClass().getInterfaces(), //必须接口
new JdkTiktokProxy(t));
return (T)o;
}
//定义目标方法的拦截逻辑;每个方法都会进来的
@Override
public Object invoke(Object proxy,
Method method,
Object[] args) throws Throwable {
//反射执行
System.out.println("真正执行被代理对象的方法");
Object invoke = method.invoke(target, args);
System.out.println("执行完返回......");
return invoke;
}
}
cglib动态代理(使用cglib时记得加依赖)
cglib在底层通过直接操作字节码的方式,使用继承的方式得到目标对象方法。
代码演示:
//要被代理增强的类
public class MyTikTok {
public void tiktok() {
System.out.println("开始直播....");
}
}
//cglib核心代码
public class CglibProxy {
//为任意对象创建代理
public static<T> T createProxy(T t){
//1、创建一个增强器
Enhancer enhancer = new Enhancer();
//2、设置要增强哪个个类的功能。增强器为这个类动态创建一个子类
enhancer.setSuperclass(t.getClass());
//3、设置回调
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object obj,
Method method,
Object[] args,
MethodProxy proxy) throws Throwable {
//编写拦截的逻辑
System.out.println("cglib开场秀 .......");
//目标方法进行执行
Object invoke = proxy.invokeSuper(obj,args);
return invoke;
}
});
Object o = enhancer.create();
return (T) o;
}
}
//测试
public class CglibTest {
public static void main(String[] args) {
MyTikTok tikTok = new MyTikTok();
MyTikTok proxy = CglibProxy.createProxy(tikTok);
proxy.tiktok();
}
}

//部分代码展示
public class Menu {
private Integer id;
private String name;
public Menu(Integer id,String name){
this.id = id;
this.name = name;
}
//组合模式关注点
private List<Menu> childs = new ArrayList<>();
//提供添加层级的方法
void addChildMenu(Menu menu){
childs.add(menu);
}
//层级遍历方法
void printMenu(){
System.out.println(name);
if(childs.size() > 0){
for (Menu child : childs) {
child.printMenu();
}
}
}
}

//办一个新身份证
public class Police {
public void resgister(String name){
System.out.println(name + "办一个新身份证");
}
}
//存学籍档案
public class Edu {
public void school(String name){
System.out.println(name+"存学籍档案");
}
}
//开通当地社保
public class Social {
public void handleSocial(String name){
System.out.println(name+"开通当地社保");
}
}
//落户小程序
public class WeiXinFacade {
Police police = new Police();
Edu edu = new Edu();
Social social = new Social();
public void handleXxx(String name){
police.resgister(name);
edu.school(name);
social.handleSocial(name);
}
}
//Test......

/**
* 可共享和不可共享状态
*/
public abstract class AbstractWaitressFlyweight {
boolean canService = true;//能否服务
//正在服务。 享元的不可共享属性留给外部进行改变的接口
abstract void service();
//服务完成。 享元的不可共享属性留给外部进行改变的接口
abstract void end();
public boolean isCanService() {
return canService;
}
}
/**
* 具体享元类
*/
@AllArgsConstructor
public class BeautifulWaitress extends AbstractWaitressFlyweight{
String id;//工号
String name;//名字
int age;//年龄
//以上是不变的
@Override
void service() {
System.out.println("工号:"+id+";"+name+" "+age+" 正在为您服务...");
//改变外部状态
this.canService = false;
}
@Override
void end() {
System.out.println("工号:"+id+";"+name+" "+age+" 服务结束...请给五星好评");
this.canService = true;
}
}
//享元工厂
public class Shop {
private static Map<String,AbstractWaitressFlyweight> pool = new HashMap<>();
//享元,池子中有对象
static {
BeautifulWaitress waitress =
new BeautifulWaitress("1111","张三",18);
BeautifulWaitress waitress2 =
new BeautifulWaitress("9527","李四",20);
pool.put(waitress.id,waitress);
pool.put(waitress2.id,waitress2);
}
public static AbstractWaitressFlyweight getWaitress(String name){
AbstractWaitressFlyweight flyweight = pool.get(name);
if(flyweight == null){
for (AbstractWaitressFlyweight value : pool.values()) {
//当前共享对象能否服务
if(value.isCanService()){
return value;
}
};
return null;
}
return flyweight;
}
}
//Test......
结构型模型到这里就学习完了,下一篇:行为型模型…