1 定义:
1.1 定义:Decouple an abstraction from its implementation so that two can vary independently.(将抽象和实现解耦,使得两者独立地变化。)
1.2 通用类图:
1.3 通用代码:
public interface Implementor {
// 基本方法
public void doSomething();
public void doAnything();
}
public class ConcreteImplementor1 implements Implementor {
public void doSomething() {
// 业务逻辑处理
}
public void doAnything() {
// 业务逻辑处理
}
}
public class ConcreteImplementor2 implements Implementor {
public void doSomething() {
// 业务逻辑处理
}
public void doAnything() {
// 业务逻辑处理
}
}
public abstract class Abstraction {
// 定义对实现化角色的引用
private Implementor imp;
// 约束子类必须实现该构造函数
public Abstraction(Implementor _imp) {
this.imp = _imp;
}
// 自身的行为和属性
public void request() {
this.imp.doSomething();
}
// 获得实现化角色
public Implementor getImp() {
return imp;
}
}
public class RefinedAbstraction extends Abstraction {
// 覆写构造函数
public RefinedAbstraction(Implementor _imp) {
super(_imp);
}
// 修正父类的行文
@Override
public void request() {
/*
* 业务处理....
*/
super.request();
super.getImp().doAnything();
}
}
public class Client {
public static void main(String[] args) {
// 定义一个实现化角色
Implementor imp = new ConcreteImplementor1();
// 定义一个抽象化角色
Abstraction abs = new RefinedAbstraction(imp);
// 执行行文
abs.request();
}
}
2 优点
2.1 抽象与实现分离:实现不用再绑定在一个固定的抽象层次上;
2.2 实现细节对客户透明:实现已经由抽象层通过聚合关系完成了封装。
3 缺点
暂无
4 应用场景
4.1 不希望或不适用使用继承的场合:如继承层次过渡,无法更细化设计颗粒等场景;
4.2 接口或抽象类不稳定的场景:
4.3 重用性要求较高的场景:采用继承则受父类的限制,不可能出现较细的粒度。
5 注意事项
主要考虑如何拆分抽象和实现,并不是一涉及继承就要考虑使用该模式。其意图是对变化的封装,尽量把变化的因素封装到最细、最小的逻辑单元中,避免风险扩散。
尤其在多层继承时,要首先考虑。
6 扩展
暂无
7 范例
7.1 公司生产产品为例:(最初版,公司与产品紧耦合)
类图如下:
源码如下:
public abstract class Corp {
/*
* 是公司就应该有生产把,甭管是什么软件公司还是制造业公司 那每个公司的生产的
* 东西都不一样,所以由实现类来完成
*/
protected abstract void produce();
/*
* 有产品了,那肯定要销售呀,不销售你公司怎么生存
*/
protected abstract void sell();
// 公司是干什么的?赚钱的呀,不赚钱傻子才干
public void makeMoney() {
// 每个公司都是一样,先生产
this.produce();
// 然后销售
this.sell();
}
}
public class HouseCorp extends Corp {
// 房地产公司就是盖房子
protected void produce() {
System.out.println("房地产公司盖房子...");
}
// 房地产卖房子,自己住那可不赚钱
protected void sell() {
System.out.println("房地产公司出售房子...");
}
// 房地产公司很High了,赚钱,计算利润
public void makeMoney() {
super.makeMoney();
System.out.println("房地产公司赚大钱了...");
}
}
public class ClothesCorp extends Corp {
// 服装公司生产的就是衣服了
protected void produce() {
System.out.println("服装公司生产衣服...");
}
// 服装公司卖服装,可只卖服装,不卖穿衣服的模特
protected void sell() {
System.out.println("服装公司出售衣服...");
}
// 服装公司不景气,但怎么说也是赚钱行业
public void makeMoney() {
super.makeMoney();
System.out.println("服装公司赚小钱...");
}
}
public class Client {
public static void main(String[] args) {
System.out.println("-------房地产公司是这个样子运行的-------");
// 先找到我的公司
HouseCorp houseCorp = new HouseCorp();
// 看我怎么挣钱
houseCorp.makeMoney();
System.out.println("\n");
System.out.println("-------服装公司是这样运行的-------");
ClothesCorp clothesCorp = new ClothesCorp();
clothesCorp.makeMoney();
}
}
7.2 公司生产产品为例:(变化版,公司生产新产品 IPOD)
类图不变:
源码改变如下:
public class IPodCorp extends Corp {
// 我开始生产iPod了
protected void produce() {
System.out.println("我生产iPod...");
}
// 山寨的iPod很畅销,便宜呀
protected void sell() {
System.out.println("iPod畅销...");
}
// 狂赚钱
public void makeMoney() {
super.makeMoney();
System.out.println("我赚钱呀...");
}
}
public class Client {
public static void main(String[] args) {
System.out.println("-------房地产公司是这个样子运行的-------");
// 先找到我的公司
HouseCorp houseCorp = new HouseCorp();
// 看我怎么挣钱
houseCorp.makeMoney();
System.out.println("\n");
System.out.println("-------山寨公司是这样运行的-------");
IPodCorp iPodCorp = new IPodCorp();
iPodCorp.makeMoney();
}
}
整个的变化了,也即原本“管理,赚钱方式”这些
不用改变的,也被推倒重来了。。。
7.3 公司生产产品为例:(更改为关联版,公司与产品仅关联)
类图如下:
源码如下:
public abstract class Product {
// 甭管是什么产品它总要是能被生产出来
public abstract void beProducted();
// 生产出来的东西,一定要销售出去,否则亏本呀
public abstract void beSelled();
}
public class House extends Product {
// 豆腐渣就豆腐渣呗,好歹也是个房子
public void beProducted() {
System.out.println("生产出的房子是这个样子的...");
}
// 虽然是豆腐渣,也是能够销售出去的
public void beSelled() {
System.out.println("生产出的房子卖出去了...");
}
}
public class IPod extends Product {
public void beProducted() {
System.out.println("生产出的iPod是这个样子的...");
}
public void beSelled() {
System.out.println("生产出的iPod卖出去了...");
}
}
public abstract class Corp {
// 定义一个产品对象,抽象的了,不知道具体是什么产品
private Product product;
// 构造函数,由子类定义传递具体的产品进来
public Corp(Product product) {
this.product = product;
}
// 公司是干什么的?赚钱的呀,不赚钱傻子才干
public void makeMoney() {
// 每个公司都是一样,先生产
this.product.beProducted();
// 然后销售
this.product.beSelled();
}
}
public class HouseCorp extends Corp {
// 定义传递一个House产品进来
public HouseCorp(House house) {
super(house);
}
// 房地产公司很High了,赚钱,计算利润
public void makeMoney() {
super.makeMoney();
System.out.println("房地产公司赚大钱了...");
}
}
public class ShanZhaiCorp extends Corp {
// 产什么产品,不知道,等被调用的才知道
public ShanZhaiCorp(Product product) {
super(product);
}
// 狂赚钱
public void makeMoney() {
super.makeMoney();
System.out.println("我赚钱呀...");
}
}
public class Client {
public static void main(String[] args) {
House house = new House();
System.out.println("-------房地产公司是这个样子运行的-------");
// 先找到房地产公司
HouseCorp houseCorp = new HouseCorp(house);
// 看我怎么挣钱
houseCorp.makeMoney();
System.out.println("\n");
// 山寨公司生产的产品很多,不过我只要指定产品就成了
System.out.println("-------山寨公司是这样运行的-------");
ShanZhaiCorp shanZhaiCorp = new ShanZhaiCorp(new IPod());
shanZhaiCorp.makeMoney();
}
}
7.4 公司生产产品为例:(最终版,产品又变回衣服时)
类图与上类似:
源码如下:
public class Client {
public static void main(String[] args) {
House house = new House();
System.out.println("-------房地产公司是这个样子运行的-------");
// 先找到房地产公司
HouseCorp houseCorp = new HouseCorp(house);
// 看我怎么挣钱
houseCorp.makeMoney();
System.out.println("\n");
// 山寨公司生产的产品很多,不过我只要指定产品就成了
System.out.println("-------山寨公司是这样运行的-------");
ShanZhaiCorp shanZhaiCorp = new ShanZhaiCorp(new Clothes());
shanZhaiCorp.makeMoney();
}
}
此时,仅改变产品参数。