凌雪
2018-10-24
来源 :网络
阅读 1117
评论 0
摘要:本文将带你了解Android应用开发之Android设计模式-- 单例模式、建造者模式,希望本文对大家学Android有所帮助。
本文将带你了解Android应用开发之Android设计模式-- 单例模式、建造者模式,希望本文对大家学Android有所帮助。
如果作为低年级入门的同学学习设计模式是比较困难的,建议先补充基础,积累经验再回过头进行学习设计模式,因为其中的重要性关乎到我们是否能够进阶成为相对优秀的Android工程师,高年级大佬麻烦多多指导。在阅读或者分析源码的时候,或多或少离不开设计模式,下面我只是挑了几个来谈谈我学习的理解。
在分享设计模式之前,我们先了解下设计模式的六大原则:
1.单一职责原则:对于一个类而言,应该仅有一个引起它变化的原因。通俗地理解是不要在Activity中写Bean文件、网络请求处理和Adapter等。
2.开放封闭原则:类、模块、函数等应该是可以拓展,但是不可以修改。在开发中,需求是变化的,如果有新的需求,我们就要重新把类改一遍显然是很爆炸的,所有进来通过扩展的方式实现
3.迪米特原则:一个软件应当尽可能少地和其他实体发生相互作用。
4.接口隔离原则:一个类对另一个类的依赖应该建立在最小的接口上,接口的负责化要适度
5.依赖倒置原则:高层模块不应该依赖底层模块,两者都应该依赖于抽象。抽象不应该依赖细节,细节应该依赖与抽象。读起来很拗口,在Java中,抽象是指接口和抽象类;细节是实现类;高层模块就是调用者,底层模块就是具体的实现类,我的理解是类跟类之间的依赖通过抽象产生的。
6.里氏替换原则:所有引用基类的地方必须能透明地使用其子类的对象。
下面进入设计模式的话题,包括了:
创造型设计模式:单例模式、建造者模式(ps:简单工厂模式和抽象工厂模式理解的还不是很好,所以先不做分享)、结构型模式中的享元模式和行为型设计模式中的策略模式、观察者模式
一、单例模式:保证一个类仅有一个实例,并且提供一个可以访问的方法
/** * 6种单例模式写法 * Created by XQM on 2018/5/13. */ //第一种,饿汉式.基于类加载机制,在类加载的时候就完成实例化,如果至始至终没有使用到该类会造成内存浪费public class SingleDemo { private static SingleDemo instance = new SingleDemo(); public static SingleDemo getInstance(){ return instance; }} //第二种,懒汉式,第一次加载时需要实例化,反应慢,在多线程并发不能保证单例public class SingleDemo{ private static SingleDemo instance; public static SingleDemo getInstance() { if (instance == null){ instance = new SingleDemo(); } return instance; }} //每次调用都需要同步,造成不必要的同步开销public class SingleDemo{ private static SingleDemo instance; public static synchronized SingleDemo getInstance() { if (instance == null){ instance = new SingleDemo(); } return instance; }} //双重检查模式DCL,在某些情况下会失效public class SingleDemo{ private static SingleDemo instance; public static SingleDemo getInstance() { if (instance == null){ synchronized (SingleDemo.class){ if (instance == null){ instance = new SingleDemo(); } } } return instance; }} //静态内部类单例模式,第一次类加载的时候并不会初始化instance,//当且仅当调用了getInstance()时JVM加载SingleDemoHolder初始化instance,//所以保证了线程安全和单例,推荐使用public class SingleDemo{ public static SingleDemo getInstance() { return SingleDemoHolder.instance; } private static class SingleDemoHolder{ private static final SingleDemo instance = new SingleDemo(); }} /** * 枚举单例 */public enum SingleDemo{ INSTANCE; private void doSomThing(){ }}
补充下JVM对内部类的加载顺序
//静态内部类单例模式,推荐使用public class SingleDemo{ public static SingleDemo getInstance() { return SingleDemoHolder.instance; } //类静态属性 public static SingleDemo testOut = new SingleDemo(1); static { System.out.println("调用静态代码块:Static function"); } private static class SingleDemoHolder{ static { System.out.println("调用匿名内部类:Inner Static"); } private static final SingleDemo instance = new SingleDemo(3); } public SingleDemo(int i) { switch (i){ case 1: System.out.println("调用静态属性: " +" Construct! "+i); break; case 2: System.out.println("调用自身构造方法: " +" Construct! "+i); break; case 3: System.out.println("调用匿名内部类静态属性: " +" Construct! "+i); break; } }} //主函数测试,根据下面的结果发现,初始化的时候,静态块和静态变量是按顺序的,内部类按需调用public class BuilderClient { public static void main(String[] args){ SingleDemo singleDemo = new SingleDemo(2); SingleDemo.getInstance(); }}
二、建造者模式:用来创建复杂对象的模式,将其部件解耦。通常Android中的Dialog或者EventBus使用的时候会碰到。
/** * 定义产品 * Created by XQM on 2018/5/13. */public class Computer { private String mCpu; private String mMain; private String mCard; private String mRam; public String getmCpu() { return mCpu; } public void setmCpu(String mCpu) { this.mCpu = mCpu; } public String getmMain() { return mMain; } public void setmMain(String mMain) { this.mMain = mMain; } public String getmCard() { return mCard; } public void setmCard(String mCard) { this.mCard = mCard; } public String getmRam() { return mRam; } public void setmRam(String mRam) { this.mRam = mRam; } @Override public String toString() { return "Computer{" + "mCpu='" + mCpu + '\'' + ", mMain='" + mMain + '\'' + ", mCard='" + mCard + '\'' + ", mRam='" + mRam + '\'' + '}'; }} /** * 抽象产品的组建 * Created by XQM on 2018/5/13. */public abstract class Builder { public abstract void buildCpu(String cpu); public abstract void buildMainboard(String main_board); public abstract void buildGraphicsCard(String graphics_card); public abstract void buildRam(String ram); public abstract Computer create();} /** * 真正的建造者,实现build的方法,然后返回组建好的对象 * Created by XQM on 2018/5/13. */public class BuildComputer extends Builder { private Computer computer = new Computer(); @Override public void buildCpu(String cpu) { computer.setmCpu(cpu); } @Override public void buildMainboard(String main_board) { computer.setmMain(main_board); } @Override public void buildGraphicsCard(String graphics_card) { computer.setmCard(graphics_card); } @Override public void buildRam(String ram) { computer.setmRam(ram); } @Override public Computer create() { return computer; }} public class Assembly { Builder builder; public Assembly(Builder builder) { this.builder = builder; } public Computer CreateComputer(String cpu ,String main,String card,String ram){ builder.buildCpu(cpu); builder.buildMainboard(main); builder.buildRam(ram); builder.buildGraphicsCard(card); return builder.create(); }} //测试主类public class BuilderClient { public static void main(String[] args){ Builder builder = new BuildComputer(); Assembly assembly = new Assembly(builder); Computer sc = assembly.CreateComputer("i7-6700","联想","890","金士顿DDR4"); System.out.println(sc.toString()); }}
三、享元模式:是池技术的重要实现方式,可以减少应用程序创建对象,降低产生OOM风险,提高程序的性能。
/** * 抽象享元角色 * Created by XQM on 2018/5/13. */public interface IGoods { void showGoodsPrice(String name);} /** * 具体享元角色,实现抽象享元角色 * Created by XQM on 2018/5/13. */public class Goods implements IGoods { private String name;//名称,内部状态 private String attribute;//属性,外部状态 public Goods(String name) { this.name = name; } @Override public void showGoodsPrice(String attribute) { if (attribute.equals("红色")){ System.out.println("有货,价格是:8974元"); }else { System.out.println("有货,价格是:8974元"); } }} /** * 享元工厂用来创建具体的享元角色,通过map来缓存对象 * 如果系统存在大量的相似对象或者缓存池的场景可以使用 * Created by XQM on 2018/5/13. */public class GoodsFactory { private static Map<string,goods> goodsMap = new HashMap<>(); public static Goods getGoods(String name){ if (goodsMap.containsKey(name)){ System.out.println("缓存中找到商品,key:"+name); return goodsMap.get(name); }else { Goods good = new Goods(name); goodsMap.put(name,good); System.out.println("创建商品,key:"+name); return good; } }} /** *测试类 * 享元模式缓存对象,避免OOM * Created by XQM on 2018/5/13. */public class FlywightClient { public static void main(String[] args){ Goods goods = GoodsFactory.getGoods("华为3e"); goods.showGoodsPrice("红色"); Goods goods1 = GoodsFactory.getGoods("华为3e"); goods1.showGoodsPrice("幻影黑"); Goods goods2 = GoodsFactory.getGoods("华为9"); goods2.showGoodsPrice("幻影黑"); }}</string,goods>
四、策略模式:定义一系列的算法,把算法封装起来,并且是它们可以相互替换,使得算法可以独立于使用它的客户而独立变化。比如代码有很多if…else或者case,会变得比较臃肿,维护成本也比较高,违背开放封闭原则,通过策略模式就可以简化。
/** * 定义一个程序开发的接口 * 抽象策略角色 * Created by XQM on 2018/5/13. */public interface IDevelopStrategy { void develop();} /** * 开发 * Created by XQM on 2018/5/13. */public class APPStrategy implements IDevelopStrategy { @Override public void develop() { System.out.println("产品发话了,需要开发APP"); }} /** * 具体的策略 * Created by XQM on 2018/5/13. */public class WebSiteStrategy implements IDevelopStrategy { @Override public void develop() { System.out.println("产品发话了,需要开发网站"); }} /** * 上下文角色的构造方法根据传递进来不同的具体策略来调用不用的develop() * 屏蔽调用者对策略的直接访问,启动承上启下作用 * Created by XQM on 2018/5/13. */public class Context { private IDevelopStrategy strategy; public Context(IDevelopStrategy strategy) { this.strategy = strategy; } public void develop(){ strategy.develop(); }} /** * 每一个策略都是一个类,复用性小 * 上层模块必须知道有哪些策略才可以使用 * Created by XQM on 2018/5/13. */public class StrategyClient { public static void main(String[] args){ Context context; //开发APP context = new Context(new APPStrategy()); context.develop(); //开发网站 context = new Context(new WebSiteStrategy()); context.develop(); }}
五、观察者模式:定义对象间一对多的依赖关系,每当一个对象改变状态时,则所有依赖于它的对象都会得到通知并且被自动更新。常见运用在发布-订阅事件总线。
/** * 把所有的观察者对象保存在一个集合中,其中每一个主题可以有任意数量的观察者,可以想象为公众号 * Created by XQM on 2018/5/13. */public interface ObservedSubject { /** * 增加观察者 * @param observer */ void add(Observer observer); /** * 删除观察者 * @param observer */ void delete(Observer observer); /** * 通知更新 * @param message */ void notify(String message);} /** * 抽象被观察者的实现类,实现添加、删除和通知观察者的方法 * Created by XQM on 2018/5/13. */public class SubcriptionSubject implements ObservedSubject { private List<observer> subscriberUsers = new ArrayList<observer>(); @Override public void add(Observer oberver) { subscriberUsers.add(oberver); } @Override public void delete(Observer observer) { subscriberUsers.remove(observer); } @Override public void notify(String message) { for (Observer observer:subscriberUsers){ observer.update(message); } }} /** * 抽象观察者 * Created by XQM on 2018/5/13. */public interface Observer { void update(String message);}/** * 具体观察者 * Created by XQM on 2018/5/13. */public class SubscriberUser implements Observer { private String name; public SubscriberUser(String name) { this.name = name; } @Override public void update(String message) { System.out.println(name+"更新了:"+message); }} /** * 优点:观察者和被观察者之间是抽象耦合,容易扩展 * 缺点:在Java中消息的通知一般是按照顺序的,如果每个观察者造成卡顿,会影响整体的效率,采用异步解决 * Created by XQM on 2018/5/13. */public class ObserverClient { public static void main(String[] args){ SubcriptionSubject subcriptionSubject = new SubcriptionSubject(); SubscriberUser user1 = new SubscriberUser("下雨了"); SubscriberUser user2 = new SubscriberUser("下雪了"); SubscriberUser user3 = new SubscriberUser("落花了"); //注册订阅 subcriptionSubject.add(user1); subcriptionSubject.add(user2); subcriptionSubject.add(user3); //发送更新给订阅者 subcriptionSubject.notify("不一样的博客更新了"); }</observer></observer>
对比下Java中的观察者实现:
import java.util.Observable; /** * 继承Observable类(被观察者发送消息),notifyObservers发送通知 * Created by XQM on 2018/3/22. */public class Gamedaily extends Observable { public void postNewArticle(String content){ //内容改变 setChanged(); //通知所有订阅者改变内容 notifyObservers(content); }} import java.util.Observable;import java.util.Observer; /** * 定义观察者,继承observer接口,实现update方法 * Created by XQM on 2018/3/22. */public class User implements Observer{ public String name; public User(String name) { this.name = name; } @Override public void update(Observable observable, Object o) { System.out.println("Hi "+name +",公众号更新了内容:"+o); }} /** * Created by XQM on 2018/3/22. */public class Client { public static void main(String[] args){ Gamedaily gamedaily = new Gamedaily(); User user0 = new User("user0"); User user1 = new User("user1"); User user2 = new User("user2"); gamedaily.addObserver(user0); gamedaily.addObserver(user1); gamedaily.addObserver(user2); gamedaily.postNewArticle("有新文章更新了"); }}
本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标移动开发之Android频道!
喜欢 | 0
不喜欢 | 0
您输入的评论内容中包含违禁敏感词
我知道了

请输入正确的手机号码
请输入正确的验证码
您今天的短信下发次数太多了,明天再试试吧!
我们会在第一时间安排职业规划师联系您!
您也可以联系我们的职业规划师咨询:
版权所有 职坐标-一站式AI+学习就业服务平台 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
沪公网安备 31011502005948号