Java中常用的10种设计模式详解

来源:互联网 发布:公司资料保密软件 编辑:程序博客网 时间:2024/06/05 17:11

1. 观察者模式

定义了对象之间的一对多的依赖,这样一来,当一个对象改变时,它的所有的依赖者都会收到通知并自动更新。

  • 对于JDK或者Andorid中都有很多地方实现了观察者模式,比如XXXView.addXXXListenter , 当然了 XXXView.setOnXXXListener不一定是观察者模式,因为观察者模式是一种一对多的关系,对于setXXXListener是1对1的关系,应该叫回调。

/**   * 注册一个观察者   */  public void registerObserver(Observer observer);  /**   * 移除一个观察者   */  public void removeObserver(Observer observer);  /**   * 通知所有观察者   */  public void notifyObservers();
  •  @Overridepublic void registerObserver(Observer observer) {    observers.add(observer);}@Overridepublic void removeObserver(Observer observer) {    int index = observers.indexOf(observer);    if (index >= 0) {        observers.remove(index);    }}@Overridepublic void notifyObservers() {    for (Observer observer : observers) {        observer.update(msg);    }}/** * 主题更新信息 */public void setMsg(String msg) {    this.msg = msg;    notifyObservers();}

public ObserverUser1(Subject subject) {       subject.registerObserver(this);   }   @Override   public void update(String msg) {       Log.e("-----ObserverUser1 ", "得到 3D 号码:" + msg + ", 我要记下来。 ");   }

  •  // 创建服务号 objectFor3D = new ObjectFor3D(); // 创建两个订阅者 observerUser1 = new ObserverUser1(objectFor3D); observerUser2 = new ObserverUser2(objectFor3D); // 两个观察者,发送两条信息 objectFor3D.setMsg("201610121 的3D号为:127"); objectFor3D.setMsg("20161022 的3D号为:000");

2. 工厂模式

简单列一下这个模式的家族:

  • 1、静态工厂模式

    • 这个最常见了,项目中的辅助类,TextUtil.isEmpty等,类+静态方法。
  • 2、简单工厂模式(店里买肉夹馍)

    • 定义:通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
     public RoujiaMo creatRoujiaMo(String type) {     RoujiaMo roujiaMo = null;     switch (type) {         case "Suan":             roujiaMo = new ZSuanRoujiaMo();             break;         case "La":             roujiaMo = new ZLaRoujiaMo();             break;         case "Tian":             roujiaMo = new ZTianRoujiaMo();             break;         default:// 默认为酸肉夹馍             roujiaMo = new ZSuanRoujiaMo();             break;     }     return roujiaMo; }
  • 3、工厂方法模式(开分店)

    • 定义:定义一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法模式把类实例化的过程推迟到子类。
    • 对比定义:
    • 1、定义了创建对象的一个接口:public abstract RouJiaMo sellRoujiaMo(String type);
    • 2、由子类决定实例化的类,可以看到我们的馍是子类生成的。
  • public abstract RoujiaMo sellRoujiaMo(String type);

  • 4、抽象工厂模式(使用官方提供的原料)

    • 定义:提供一个接口,用于创建相关的或依赖对象的家族,而不需要明确指定具体类。
    • 对比定义:
      • 1、提供一个接口:public interface RouJiaMoYLFactroy
      • 2、用于创建相关的或依赖对象的家族 public Meat createMeat();public YuanLiao createYuanliao();我们接口用于创建一系列的原材料
     /** * 准备工作 */public void prepare(RoujiaMoYLFactory roujiaMoYLFactory) {    Meet meet = roujiaMoYLFactory.creatMeet();    YuanLiao yuanLiao = roujiaMoYLFactory.creatYuanLiao();    Log.e("---RoujiaMo:", "使用官方的原料 ---" + name + ": 揉面-剁肉-完成准备工作 yuanLiao:"+meet+"yuanLiao:"+yuanLiao);}

3. 单例设计模式

单例模式主要是为了避免因为创建了多个实例造成资源的浪费,且多个实例由于多次调用容易导致结果出现错误,而使用单例模式能够保证整个应用中有且只有一个实例

  • 定义:只需要三步就可以保证对象的唯一性

    • (1) 不允许其他程序用new对象
    • (2) 在该类中创建对象
    • (3) 对外提供一个可以让其他程序获取该对象的方法
  • 对比定义:

    • (1) 私有化该类的构造函数
    • (2) 通过new在本类中创建一个本类对象
    • (3) 定义一个公有的方法,将在该类中所创建的对象返回

    private SingletonLanHan() {}    private static SingletonLanHan singletonLanHanFour;    public static SingletonLanHan getSingletonLanHanFour() {       if (singletonLanHanFour == null) {   synchronized (SingletonLanHan.class) {       if (singletonLanHanFour == null) {   singletonLanHanFour = new SingletonLanHan();       }   }       }       return singletonLanHanFour;   }   

4. 策略模式

策略模式:定义了算法族,分别封装起来,让它们之间可相互替换,此模式让算法的变化独立于使用算法的客户。

  • 以创建游戏角色为例子:
    • 最初的游戏角色的父类
    • 发现有重复代码后,重构后的父类
  • 总结:
    • 1、封装变化(把可能变化的代码封装起来)
    • 2、多用组合,少用继承(我们使用组合的方式,为客户设置了算法)
    • 3、针对接口编程,不针对实现(对于Role类的设计完全的针对角色,和技能的实现没有关系)
  • 最后测试:创建角色:
RoleA roleA = new RoleA("---A");roleA.setiDisplayBehavior(new DisplayYZ())      .setiAttackBehavior(new AttackXL())      .setiDefendBehavior(new DefendTMS())      .setiRunBehavior(new RunJCTQ());roleA.display();// 样子roleA.attack();// 攻击roleA.run();// 逃跑roleA.defend();// 防御

5. 适配器模式

定义:将一个类的接口转换成客户期望的另一个接口,适配器让原本接口不兼容的类可以相互合作。这个定义还好,说适配器的功能就是把一个接口转成另一个接口。

  • 以充电器为实例: 手机充电器一般都是5V左右吧,咱天朝的家用交流电压220V,所以手机充电需要一个适配器(降压器)


  • 最后测试:给手机冲个电:

    Mobile mobile = new Mobile();V5Power v5Power = new V5PowerAdapter(new V200Power());mobile.inputPower(v5Power);

6. 命令模式

定义:将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。(简化: 将请求封装成对象,将动作请求者和动作执行者解耦。)

  • 需求:最近智能家电很火热,假设现在有电视、电脑、电灯等家电,现在需要你做个遥控器控制所有家电的开关,要求做到每个按钮对应的功能供用户个性化,对于新买入家电要有非常强的扩展性。
QuickCommand quickCloseCommand = new QuickCommand(new Command[]{new LightOffCommand(light), new ComputerOffCommand(computer), new DoorCloseCommand(door)});controlPanel.setCommands(6, quickOpenCommand);controlPanel.keyPressed(6);
controlPanel.setCommands(0, new DoorOpenCommand(door));// 开门controlPanel.keyPressed(0);

7. 装饰者模式

装饰者模式:若要扩展功能,装饰者提供了比集成更有弹性的替代方案,动态地将责任附加到对象上。

  • 先简单描述下装饰者模式发挥作用的地方,当我们设计好了一个类,我们需要给这个类添加一些辅助的功能,并且不希望改变这个类的代码,这时候就是装饰者模式大展雄威的时候了。这里还体现了一个原则:类应该对扩展开放,对修改关闭。

  • 需求:设计游戏的装备系统,基本要求,要可以计算出每种装备在镶嵌了各种宝石后的攻击力和描述:

  • 5、最后测试:计算攻击力和查看描述:

     Log.e("---", "一个镶嵌2颗红宝石,1颗蓝宝石的靴子: "); IEquip iEquip = new RedGemDecotator(new RedGemDecotator(new BlueGemDecotator(new ShoeEquip()))); Log.e("---", "攻击力:" + iEquip.caculateAttack()); Log.e("---", "描述语:" + iEquip.description());

8. 外观模式

定义:提供一个统一的接口,用来访问子系统中的一群接口,外观定义了一个高层的接口,让子系统更容易使用。其实就是为了方便客户的使用,把一群操作,封装成一个方法。

  • 需求:我比较喜欢看电影,于是买了投影仪、电脑、音响、设计了房间的灯光、买了爆米花机,然后我想看电影的时候,我需要一键观影和一键关闭。

  • 每个设备类的开关等操作:

  • /** * 一键观影 */public void watchMovie() {    computer.on();    light.down();    popcornPopper.on();    popcornPopper.makePopcorn();    projector.on();    projector.open();    player.on();    player.make3DListener();}
  • 最后测试:一键观影:

     new HomeTheaterFacade(computer, light, player, popcornPopper, projector).watchMovie();

9. 模板方法模式

定义:定义了一个算法的骨架,而将一些步骤延迟到子类中,模版方法使得子类可以在不改变算法结构的情况下,重新定义算法的步骤。

  • 需求:简单描述一下:本公司有程序猿、测试、HR、项目经理等人,下面使用模版方法模式,记录下所有人员的上班情况

  • 模板方法模式中的三类角色

  • 1、具体方法(Concrete Method)

  • 2、抽象方法(Abstract Method)

  • 3、钩子方法(Hook Method)


  •  // 具体方法 public final void workOneDay() {     Log.e("workOneDay", "-----------------work start----------------");     enterCompany();     work();     exitCompany();     Log.e("workOneDay", "-----------------work end----------------"); } // 工作  抽象方法 public abstract void work(); // 钩子方法 public boolean isNeedPrintDate() {     return false; } private void exitCompany() {     if (isNeedPrintDate()) {         Log.e("exitCompany", "---" + new Date().toLocaleString() + "--->");     }     Log.e("exitCompany", name + "---离开公司"); }
  •  /**  * 重写父类的此方法,使可以查看离开公司时间  */ @Override public boolean isNeedPrintDate() {     return true; }
  • 最后测试:

    • 查看所有人员的工作情况:

       QAWorker qaWorker = new QAWorker("测试人员"); qaWorker(); HRWorker hrWorker = new HRWorker("莉莉姐"); hrWorker.workOneDay(); ...
    • 查看程序猿离开公司的时间:

       ITWorker itWorker = new ITWorker("jingbin");itWorker.workOneDay();

10. 状态模式

定义:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。

  • 定义又开始模糊了,理一下,当对象的内部状态改变时,它的行为跟随状态的改变而改变了,看起来好像重新初始化了一个类似的。

  • 需求:已自动售货机为例(有已投币、未投币等状态和投币、投币等方法)

  • // 放钱public void insertMoney() {    currentState.insertMoney();}// 退钱public void backMoney() {    currentState.backMoney();}// 转动曲柄public void turnCrank() {    currentState.turnCrank();    if (currentState == soldState || currentState == winnerState) {        currentState.dispense();//两种情况会出货    }}// 出商品public void dispense() {    Log.e("VendingMachineBetter", "---发出一件商品");    if (count > 0) {        count--;    }}// 设置对应状态public void setState(State state) {    this.currentState = state;}
  • 改进后的售货机测试:

     // 初始化售货机,且里面有3个商品VendingMachineBetter machineBetter = new VendingMachineBetter(3);machineBetter.insertMoney();machineBetter.turnCrank();
原创粉丝点击