前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >每天5分钟-结构型模式(二)

每天5分钟-结构型模式(二)

作者头像
用户8902830
发布2021-08-12 11:02:07
1890
发布2021-08-12 11:02:07
举报
文章被收录于专栏:CodeNone

桥接模式

桥接模式的目标是「将抽象与实现解耦」,使得两者可以「独立地变化」。桥接模式通过在公共接口和实现中使用继承来达到目的。

比如手机可以有多个品牌,那么可以把手机抽象出来;每个手机可以有多种实现,比如颜色不同、尺寸不同、性能不同和系统不同等等。

Abstraction: 抽象类 Implementation: 抽象的实现类 Refined: 扩充的抽象类 Specific Implementation: 具体实现类。 ❞

桥接模式UML类图

桥接模式

Abstraction

代码语言:javascript
复制
public abstract class AbstractionPhone {
    Implementor implementor;

    public Implementor getImplementorAppearance() {
        return implementor;
    }

    public void setImplementorAppearance(Implementor implementor) {
        this.implementor = implementor;
    }

    public abstract void operation();
}

Refined

代码语言:javascript
复制
public class RefineAbstractionOnePlus extends AbstractionPhone {

    @Override
    public void operation() {
        System.out.println("一加手机");
        implementor.operation();
    }
}
代码语言:javascript
复制
public class RefinedAbstractionPhoneApple extends AbstractionPhone {


    @Override
    public void operation() {
        System.out.println("苹果手机");
        implementor.operation();
    }
}

Implementor

代码语言:javascript
复制
public abstract class Implementor {
    public abstract void operation();
}

Concrete Implementor

代码语言:javascript
复制
public class ConcreteImplementorColor extends Implementor {
    @Override
    public void operation() {
        System.out.println("手机有关颜色的实现");
    }
}
代码语言:javascript
复制
public class ConcreteImplementorSize extends Implementor {
    @Override
    public void operation() {
        System.out.println("有关手机尺寸大小的实现");
    }
}

Client

代码语言:javascript
复制
public class Client {
    public static void main(String[] args) {
        AbstractionPhone phone = new RefineAbstractionOnePlus();
        phone.setImplementorAppearance(new ConcreteImplementorColor());
        phone.operation();
        phone.setImplementorAppearance(new ConcreteImplementorSize());
        phone.operation();
    }
}

组合模式

组合模式顾名思义就是「把一组对象组合成一个复杂的单一整体」,比如把对象组合成树形或者图形结构。

最简单常见的就是公司里面的人员分布,所有的员工是很复杂很多的,但是从CEO到最底层的员工会形成一个树结构。

Component: 抽象结点 Leaf: 叶子结点 Composite: 复合节点,该结点包括复合结点的子节点或者叶子结点的子结点 ❞

组合模式UML类图

组合模式

Component

代码语言:javascript
复制
public abstract class ComponentEmployee {
    String name;      //名字
    String position;   //职位
    String salary;    //薪水

    //报告人员情况
    public void report() {
        String str =  "Employee{" +
                "name='" + name + '\'' +
                ", position='" + position + '\'' +
                ", salary='" + salary + '\'' +
                '}';

        System.out.println(str);
    }

    public ComponentEmployee(String name, String position, String salary) {
        this.name = name;
        this.position = position;
        this.salary = salary;
    }

    //招聘员工
    public abstract void addEmployee(ComponentEmployee componentEmployee);

    //解雇员工
    public abstract void deleteEmployee(ComponentEmployee componentEmployee);

}

Composite

代码语言:javascript
复制
public class CompositeLeader extends ComponentEmployee {
    
    //这里本来应该是private,然后外部通过get获取才合适,为了演示
    List<ComponentEmployee> subComponentEmployees;

    public CompositeLeader(String name, String position, String salary) {
        super(name, position, salary);
        //new一个下一层员工的List集合
        subComponentEmployees = new ArrayList<>();
    }

    @Override
    public void addEmployee(ComponentEmployee componentEmployee) {
        subComponentEmployees.add(componentEmployee);
    }

    @Override
    public void deleteEmployee(ComponentEmployee componentEmployee) {
        subComponentEmployees.remove(componentEmployee);
    }

    @Override
    public void report() {
        System.out.println("我的情况:");
        super.report();

        System.out.println("我手下员工的情况");

        for (ComponentEmployee e: subComponentEmployees) {
            e.report();
        }
    }
}

Leaf

代码语言:javascript
复制
public class LeafStaff extends ComponentEmployee {
    public LeafStaff(String name, String position, String salary) {
        super(name, position, salary);
    }

    //手底都没有员工,增加和删除操作就空实现,注意这里的空实现
    @Override
    public void addEmployee(ComponentEmployee componentEmployee) {

    }

    @Override
    public void deleteEmployee(ComponentEmployee componentEmployee) {

    }

    @Override
    public void report() {
        super.report();
    }
}

可以注意到叶子结点里面有两个是空实现(因为最底层的员工手下没有其它员工),这样是不太安全的做法。很简单,只要Component 中的两个抽象方法删掉即可,然后在Composite 里面是新增方法,而不是重写方法。

外观模式(门面模式)

门面模式的目的是为复杂的子系统提供单一的统一的接口,这样客户端「只需要了解结果,不必了解各个子系统间是如何运作的。」

比如甲方尽管给产品经理提需求,他只要成品,至于说公司的内部是如调配如何完成,客户一概不理也没必要知道。

Facade: 子系统接口 SubSystem: 子系统中定义的类 ❞

门面模式UML类图

门面模式

Facade

代码语言:javascript
复制
public class FacadeLeader {
    private SubSystemArt subSystemArt = new SubSystemArt();
    private SubSystemDevelopment subSystemDevelopment = new SubSystemDevelopment();
    private SubSystemOperations subSystemOperations = new SubSystemOperations();

    //暴露给外界的方法,外界不知道具体内部是谁来干,干什么
    public void needArt() {
        subSystemArt.art();
    }

    public void needDevelop() {
        subSystemDevelopment.develop();
    }

    public void needOperation() {
        subSystemOperations.operate();
    }

}

SubSystem

代码语言:javascript
复制
public class SubSystemArt {
    public void art() {
        System.out.println("美工部门正在画图");
    }
}
代码语言:javascript
复制
public class SubSystemDevelopment {
    public void develop() {
        System.out.println("开发部门正在开发");
    }
}
代码语言:javascript
复制
public class SubSystemOperations {
    public void operate() {
        System.out.println("运维部门正在测试!");
    }
}

Client

代码语言:javascript
复制
public class Client {

    public static void main(String[] args) {
        FacadeLeader facadeLeader = new FacadeLeader();
        System.out.println("我们需要这个需求");
        facadeLeader.needArt();
        facadeLeader.needDevelop();
        facadeLeader.needOperation();
    }
    
}

享元模式

享元模式,听起来很高大上,但是实际上就是「共享对象」的一种模式。目的是通过在相似对象间的共享状态来减少内存占用。

比如王者里面的小兵在一定时间内攻击、双抗,移动速度都是一定的,那么就是通过享元模式来减少对象的生成,从而使得内存消耗较少。而对于那些打完主宰后的兵,因为不是重复的,所以可以作为非共享的状态。

Flyweight: 抽象享元类 Concrete Flyweight: 与其同伴共享状态的享元对象 Unshared Concrete Flyweight: 不共享其状态的享元对象 Flyweight Factory: 享元工厂类 ❞

享元模式UML类图

享元模式

Flyweight

代码语言:javascript
复制
public abstract class FlyweightSoldier {
    public abstract void play();
}

Concrete Flyweight

代码语言:javascript
复制
public class ConcreteFlyweightNormalSoldier extends FlyweightSoldier {
    String type;

    public ConcreteFlyweightNormalSoldier(String type) {
        this.type = type;
    }

    @Override
    public void play() {
        System.out.println("生成小兵:" + type);
    }
}

Unshared Concrete Flyweight

代码语言:javascript
复制
public class UnsharedConcreteFlyweightGeneral extends FlyweightSoldier {
    @Override
    public void play() {
        System.out.println("根据不同情况生成的龙");
    }
}

Flyweight Factory

代码语言:javascript
复制
public class FlyweightFactory {
    private Hashtable<String, FlyweightSoldier> flyweights = new Hashtable<>();

    public ConcreteFlyweightNormalSoldier getSoldier(String key) {
        if (!flyweights.contains(key)) {
            flyweights.put(key, new ConcreteFlyweightNormalSoldier(key));
        }

        return (ConcreteFlyweightNormalSoldier) flyweights.get(key);
    }

    public UnsharedConcreteFlyweightGeneral getGeneral(String key) {
        flyweights.put(key, new UnsharedConcreteFlyweightGeneral());
        return (UnsharedConcreteFlyweightGeneral) flyweights.get(key);
    }
}

这里注意了,因为普通小兵是共享的,所以当有key的时候就不用再new一个小兵,直接返回即可;而对于特殊小兵来说,不管是否有key,都会new一个兵put进去。

Client

代码语言:javascript
复制
public class Client {
    public static void main(String[] args) {
        FlyweightFactory factory = new FlyweightFactory();

        for (int i = 0; i < 3; i++) {
            System.out.println("第" + i + 1 + "波兵线");
            factory.getSoldier("近战兵").play();
            factory.getSoldier("弓箭手").play();
            factory.getSoldier("法师兵").play();
        }
        //到这里其实只创建了三个对象

        for (int i = 0; i < 2; i++) {
            System.out.println("第" + i + "波特殊兵线");
            factory.getGeneral("减双抗龙").play();
            factory.getGeneral("减攻速龙").play();
        }
        //到这里创建了7个对象,3 + 4
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-05-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 CodeNone 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 桥接模式
    • 桥接模式UML类图
      • 桥接模式
      • 组合模式
        • 组合模式UML类图
          • 组合模式
          • 外观模式(门面模式)
            • 门面模式UML类图
              • 门面模式
              • 享元模式
                • 享元模式UML类图
                  • 享元模式
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档