开发中常用的设计模式,面试时问题解答 及 简单手写下( 装饰模式 策略模式 观察者模式)

本文介绍面试提问率较高的装饰、策略、观察者模式。装饰模式可动态扩展对象功能;策略模式封装算法并可相互替换,避免多重条件语句;观察者模式定义对象间一对多依赖关系,状态改变时通知依赖对象。文中给出简单代码示例及使用场景、优缺点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上篇博客介绍了单例,简单工厂、工厂模式,
https://blog.youkuaiyun.com/liuguangxu1988/article/details/82053951
这次下篇带来面试提问率相对较高的装饰、策略、观察者模式。同样,简单描述,外加手写个小例子,代码实现,下面介绍,结合了网上的一些资料,仿照了刘望舒大神分享的例子,给大神做个广告,《Android进阶之光》写的不错,推荐大家阅读购买。

一 装饰模式

装饰模式是结构型设计模式之一,其在不必改变类文件和使用继承的情况下,动态扩展一个对象的功能,是继承的替代方案之一。通过创建一个包装对象(也就是装饰),来包裹真实对象。

装饰模式涉及角色
抽象组件:可以是接口或是抽象类
抽象组件具体实现类:被装饰的具体对象
抽象装饰者:扩展抽象组件的功能
抽象装饰者具体实现类:不同的装饰者实现不同的行为

代码举例具体实现
杨过本身会全真剑法,洪七公教了打狗棒法,欧阳锋教了蛤蟆功,洪七公和欧阳峰起到了装饰作用。
1抽象组件:武侠抽象类,抽象攻击方法

public abstract class Swordsman{
    public abstract void attack();
}

2抽象组件具体实现类(被装饰的具体对象)

public class YangGuo extends Swordsman{
    @override
    public void attack(){
        //杨过初始武学是全真剑法
        System.out.println("杨过使用全真剑法");
    }
}

3抽象装饰者(保持了一个对抽象组件的引用,方便调用被装饰对象中的方法)

public abstract class Master extends Swordsman{
    private  Swordsman mSwordsman;
    public Master(Swordsman mSwordsman){
        this.mSwordsman = mSwordsman;
    }
    @override
    public void attack(){
        mSwordsman.attack();
    }
}

4抽象装饰者的具体实现

public class HongQiGong extends Master{
    public HongQiGong(Swordsman mSwordsman){
        super(mSwordsman);
    }
    @override
    public void attack(){
        super.attack();
        teachAttack();
    }
    public void teachAttack(){
        System.out.println("洪七公教授打狗棒法");
        System.out.println("杨过使用打狗棒法");
    }
}

public class OuYangFeng extends Master{
    public OuYangFeng(Swordsman mSwordsman){
        super(mSwordsman);
    }
    @override
    public void attack(){
        super.attack();
        teachAttack();
    }
    public void teachAttack(){
        System.out.println("欧阳锋教授蛤蟆功");
        System.out.println("杨过使用蛤蟆功");
    }
}

5客户端调用

public class Client{
    public static void main(String[] args){
        YangGuo mYangGuo = new YangGuo();
        //洪七公教授打狗棒法,杨过学会了打狗棒法
        HongQiGong mHongQiGong = new HongQiGong(mYangGuo);
        mHongQiGong.attack();
        //欧阳锋教授蛤蟆功,杨过学会了蛤蟆功
        OuYangFeng mOuYangFeng = new OuYangFeng(mYangGuo);
        mOuYangFeng.attack();
    }
}

使用场景
*在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
*这些动态增加的功能可以动态撤销。
*当不能采用继承的方式对系统进行扩充,或者采用继承不利于扩展和维护时。
优点
动态扩展,运行时选择不同的装饰者,实现不同的行为。灵活。
缺点
比继承更加容易出错,排错困难。装饰层次不能过多,否则会影响效率。

二 策略模式

当我们写代码时,有很多选择,衍生if…else…如果一个条件语句中又包含多个条件语句,代码就会变得臃肿。
策略模式:定义一系列算法,把每一个算法封装起来,并且使他们可相互替换。策略模式使得算法可独立于使用它们的客户而独立变化。
设计如下角色
Context : 承上启下,屏蔽高层模块对策略、算法的直接访问。
Stragety : 抽象策略角色,策略、算法的抽象,通常为接口。
ConcreteStragety : 策略的就实现。
举例
张无忌遇到很多对手,每个都用大招,不明智,于是想出3中策略,对付3种实力的对手。
1定义策略接口

public interface FightingStragety{
    public void fighting();
}

2分别定义3个策略实现接口

public class WeakrivalStragety implements FightingStragety{
    @override
    public void fighting(){
        System.out.println("弱对手,使用太极剑");
    }
}
public class CommonrivalStragety implements FightingStragety{
    @override
    public void fighting(){
        System.out.println("普通对手,使用圣火令");
    }
}
public class StrongrivalStragety implements FightingStragety{
    @override
    public void fighting(){
        System.out.println("强大对手,使用乾坤大挪移");
    }
}

3上下文角色 通过传进来的不同的具体策略,调用不同的战斗方法

public class Context{
    private FightingStragety fightingStragety;
    public Context(FightingStragety fightingStragety){
        this.fightingStragety = fightingStragety;
    }
    public void fighting(){
        fightingStragety.fighting();
    }
}

4客户端调用 举例省略了对实力的判断

public class ZhangWuJi{
    public static void main(String[] args){
        Context context;
        //遇到宋青书,弱对手策略
        context = new Context(new WeakrivalStragety());
        context.fighting();
        //遇到灭绝师太,普通对手策略
        context = new Context(new CommonrivalStragety());
        context.fighting();
        //遇到成昆,强大对手策略
        context = new Context(new StrongrivalStragety());
        context.fighting();
    }
}

使用场景
*对客户隐藏具体策略(算法)的实现细节,彼此完全独立。
*一个类定义了很多行为,这些行为以多个条件语句形式出现。策略模式将相关的条件分支移入他们各自的Stragety类中,以代替这些条件语句。
优点
避免使用多重条件语句,易于扩展。多重条件语句不移维护,易出错。
缺点
每个策略都是一个类,复用性小,策略过多,类的数量过多。

三 观察者模式

又称发布-订阅模式,属于行为设计模式的一种。定义对象间一种一对多的依赖关系,每当一个对象改变状态时,则所有依赖于他的对象都会得到通知并自动更新。
涉及如下
Subject:抽象被观察者,抽象主题角色把所有观察者对象保存在一个集合里,每个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象。
ConcreteSubject:具体被观察者,该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知。
Observer:抽象观察者,是观察者者的抽象类,它定义了一个更新接口,使得在得到主题更改通知时更新自己。
ConcrereObserver:具体观察者,实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。

代码的简单实现 举例 韦小宝风流,老婆们看的紧,做什么事之前要报告
1抽象观察者

public interface Observer {
    public void update(String message);
}

2具体观察者(七个老婆)

public class GirlFriend implements Observer {
    private String name;
    public GirlFriend(String name) {
        this.name = name;
    }
    @Override
    public void update(String message) {
        System.out.println(name + "收到消息----" + message);
    }
}

3抽象被观察者

public interface Subject {
    // 增加订阅者
    public void attach(Observer observer);
    //删除订阅者
    public void detach(Observer observer);
    //通知订阅者更新消息
    public void notify(String message);
}

4具体被观察者(小宝)

public class WeiXiaoBao implements Subject {
    //储存观察者
    private List<Observer> list = new ArrayList<Observer>();
    @Override
    public void attach(Observer observer) {
        list.add(observer);
    }
    @Override
    public void detach(Observer observer) {
        list.remove(observer);
    }
    @Override
    public void notify(String message) {
        for (Observer observer : list) {
            observer.update(message);
        }
    }
}

5客户端调用

public class Client {
    public static void main(String[] args) {
        WeiXiaoBao mWeiXiaoBao = new WeiXiaoBao ();
        //创建女朋友(观察者)
        GirlFriend mGirlFriend1 = new GirlFriend("双儿");
        GirlFriend mGirlFriend2 = new GirlFriend("建宁");
        GirlFriend mGirlFriend3 = new GirlFriend("阿珂");
        //观察韦小宝(订阅)
        mWeiXiaoBao.attach(mGirlFriend1);
        mWeiXiaoBao.attach(mGirlFriend2);
        mWeiXiaoBao.attach(mGirlFriend3);
        //韦小宝发出消息给订阅的女朋友
        mWeiXiaoBao.notify("我去天地会找师傅下棋去了");
    }
}

输出结果
双儿 收到消息—-我去天地会找师傅下棋去了
建宁 收到消息—-我去天地会找师傅下棋去了
阿珂 收到消息—-我去天地会找师傅下棋去了

使用场景
*关联行为场景,事件多级触发场景。
跨系统的消息交换场景,如消息队列、事件总线的处理机制。
优点
解除耦合,让耦合的双方都依赖于抽象,从而使得各自的变换都不会影响另一边的变换。
缺点
在应用观察者模式时需要考虑一下开发效率和运行效率的问题,程序中包括一个被观察者、多个观察者,开发、调试等内容会比较复杂,而且在Java中消息的通知一般是顺序执行,那么一个观察者卡顿,会影响整体的执行效率,在这种情况下,一般会采用异步实现。

总结

这边博客参考了刘望舒大神的 Android进阶之光 中的例子,思路比较清晰,代码示例较为生动,大家可以理解后,具体复杂的实现。如果面试时被问到也可说下,代码不多,手写也没问题,也是会加分的。最后还是码字不易,点个赞呗,哈哈。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值