桥接模式的目标是「将抽象与实现解耦」,使得两者可以「独立地变化」。桥接模式通过在公共接口和实现中使用继承来达到目的。
比如手机可以有多个品牌,那么可以把手机抽象出来;每个手机可以有多种实现,比如颜色不同、尺寸不同、性能不同和系统不同等等。
❝
Abstraction:
抽象类Implementation:
抽象的实现类Refined:
扩充的抽象类Specific Implementation:
具体实现类。 ❞
Abstraction
public abstract class AbstractionPhone {
Implementor implementor;
public Implementor getImplementorAppearance() {
return implementor;
}
public void setImplementorAppearance(Implementor implementor) {
this.implementor = implementor;
}
public abstract void operation();
}
Refined
public class RefineAbstractionOnePlus extends AbstractionPhone {
@Override
public void operation() {
System.out.println("一加手机");
implementor.operation();
}
}
public class RefinedAbstractionPhoneApple extends AbstractionPhone {
@Override
public void operation() {
System.out.println("苹果手机");
implementor.operation();
}
}
Implementor
public abstract class Implementor {
public abstract void operation();
}
Concrete Implementor
public class ConcreteImplementorColor extends Implementor {
@Override
public void operation() {
System.out.println("手机有关颜色的实现");
}
}
public class ConcreteImplementorSize extends Implementor {
@Override
public void operation() {
System.out.println("有关手机尺寸大小的实现");
}
}
Client
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:
复合节点,该结点包括复合结点的子节点或者叶子结点的子结点 ❞
Component
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
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
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:
子系统中定义的类 ❞
Facade
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
public class SubSystemArt {
public void art() {
System.out.println("美工部门正在画图");
}
}
public class SubSystemDevelopment {
public void develop() {
System.out.println("开发部门正在开发");
}
}
public class SubSystemOperations {
public void operate() {
System.out.println("运维部门正在测试!");
}
}
Client
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:
享元工厂类 ❞
Flyweight
public abstract class FlyweightSoldier {
public abstract void play();
}
Concrete Flyweight
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
public class UnsharedConcreteFlyweightGeneral extends FlyweightSoldier {
@Override
public void play() {
System.out.println("根据不同情况生成的龙");
}
}
Flyweight Factory
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
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
}
}