文章目录

  • 一:简单工厂模式:代码无错就是优?
  • 二:策略模式:出行(公交,打车。。。)(android中的动画)
  • 三:装饰模式 ---->>>android源码中:Context和ContextIml
  • 四. 代理模式----(为别人做嫁衣)
  • 五. 工厂模式:
  • 六. 原型模式 (Intent 等)
  • 七. 模版模式:
  • 八. Builder模式
  • 九:抽象工厂模式
  • 十:状态模式(电视遥控器)(开关Wi-Fi等等)
  • 十一:观察者模式
  • 十二:适配器模式(姚明去NBA打篮球需要翻译)
  • 十三:备忘录模式
  • 十四: 组合模式(View 和ViewGroup),公司故事
  • 十五:迭代器模式
  • 十六:单例模式。
    • 懒汉模式
    • Double Check Lock (DCL) 实现单例,
  • 十七: 桥接模式
  • 十八: 命令模式 (几乎体现了设计模式的所有的通病,就是类的膨胀)
    • 敏捷开发原则告诉我们,不要为代码添加基于猜测的,实际不需要的功能,如果不清楚一个系统是否需要命令模式,一般就不要着急去实现它。
  • 十九: 责任链模式:
  • 二十: 中介者模式
  • 二十一:解释器模式
  • 二十二:访问者模式

一:简单工厂模式:代码无错就是优?

    属于工厂模式,是一种弱化的工厂模式
    public class OperationFactory{public static Operation creatOperate(String operate){Operation oper = null;switch(operate){case "+":oper = new OperationAdd();break;case "-":oper = new OperationSub();break;case "*":oper = new OperationMul();break;case "/":oper = new OperationDiv();break;  }return oper;}}

二:策略模式:出行(公交,打车。。。)(android中的动画)

定义:策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们能相互替换。
  • 计算规则接口
//定义计算接口public interface CalculateStrategy{int caluculatePrice(int km);}
  • 公交计算价格策略
    //公交车价格计算策略public class BusStrategy implements CalculateStrategy{/*** 北京公交车,十公里之内一元钱,超过十公里每加一元钱,可以多乘5公里** @param km* @return*/@Overridepublic int caluculatePrice(int km) {//超过10公里总距离int extraTotal = km - 10;//超过距离是5公里的倍数int extraFactor = extraTotal / 5;//超过5公里的地方对5公里取余int faction = extraTotal % 5;//价格计算int price = 1 + extraFactor * 1;return faction > 0 ? ++price : price;}}
  • 地铁价格计算
   /**
* 作者:${xiaojiukeji} on 17/5/21 16:55
* 作用: 地铁价格计算策略
*/public class SubwayStrategy implements CalculateStrategy {/*** 6公里(含)3元,   6 ~~ 12公里(含)4元;* 12 -- 22(含)公里,5元;   22 - 32 公里(含),6元** @param km* @return*/@Overridepublic int caluculatePrice(int km) {if (km <= 6) {return 3;} else if (km > 6 && km <= 12) {return 4;} else if (km > 12 && km <= 22) {return 5;} else if (km > 22 && km <= 32) {return 6;}//其他距离简化为7元return 7;}
}
  • 定义一个扮演着Context角色的类

public class TranficCalculator {CalculateStrategy calculateStrategy;public TranficCalculator(CalculateStrategy calculateStrategy) {this.calculateStrategy = calculateStrategy;}//上下文接口public void contextStrategy(int km) {calculateStrategy.caluculatePrice(km);}
}
  • 执行类
//公交出行价格计算器public class TrainficCalator {public static void main(String[] args) {TranficCalculator calculator = new TranficCalculator(new BusStrategy());//随意改变公交工具,对扩展开放,对修改关闭calculator.contextStrategy(16);//公交16公里的价格}
}

三:装饰模式 ---->>>android源码中:Context和ContextIml

  • 汉堡基类(被装饰者)
public abstract class Humburger {protected  String name ;public String getName(){return name;}public abstract double getPrice();}
  • 鸡腿堡类(被装饰者的初始状态,有些自己的简单装饰)
public class ChickenBurger extends Humburger {public ChickenBurger() {name = "鸡腿堡";}@Overridepublic double getPrice() {return 10;}
}
  • 配料的基类(装饰者,用来对汉堡进行多层装饰,每层装饰增加一些配料)
public abstract class Condiment extends Humburger {public abstract String getName();
}
  • 生菜(装饰者的第一层)
public class Lettuce extends Condiment {Humburger humburger;public Lettuce(Humburger humburger){this.humburger = humburger;}@Overridepublic String getName() {return humburger.getName()+" 加生菜";}@Overridepublic double getPrice() {return humburger.getPrice()+1.5;}
}
  • 辣椒(装饰者的第二层)
public class Chilli extends Condiment {Humburger humburger;public Chilli(Humburger humburger) {this.humburger = humburger;//new Lettuce(new ChickenBurger());}@Overridepublic String getName() {return humburger.getName() + " 加辣椒";}@Overridepublic double getPrice() {return humburger.getPrice();  //辣椒是免费的哦}
}
  • 测试类,测试被装饰的结果
public class Test {public static void main(String[] args) {Humburger humburger = new ChickenBurger();System.out.println(humburger.getName() + "  价钱:" + humburger.getPrice());Lettuce lettuce = new Lettuce(humburger);System.out.println(lettuce.getName() + "  价钱:" + lettuce.getPrice());Chilli chilli = new Chilli(humburger);System.out.println(chilli.getName() + "  价钱:" + chilli.getPrice());Chilli chilli2 = new Chilli(lettuce);System.out.println(chilli2.getName() + "  价钱:" + chilli2.getPrice());//        鸡腿堡  价钱:10.0
//        鸡腿堡 加生菜  价钱:11.5
//        鸡腿堡 加辣椒  价钱:10.0
//        鸡腿堡 加生菜 加辣椒  价钱:11.5}
}

关键点:

  1. Condiment抽象类中,持有Humburger接口,方法全部委托给该接口调用,目的是交给该接口的实现类即子类进行调用。
  2. Condiment抽象类的子类(具体装饰者),里面都有一个构造方法调用super(Humburger),这一句就体现了抽象类依赖于子类实现即抽象依赖于实现的原则。因为构造里面参数都是humburger接口,只要是该Humburger的实现类都可以传递进去,即表现出Condiment cd = new Chilli(new Lettuce(new ChickenBurger()));这种结构的样子。,而该super已经由构造传递并指向了具体的某一个装饰者类(这个可以根据需要调换顺序),那么调用的即为装饰类的方法,然后才调用自身的装饰方法,即表现出一种装饰、链式的类似于过滤的行为。
  3. 具体被装饰者类,可以定义初始的状态或者初始的自己的装饰,后面的装饰行为都在此基础上一步一步进行点缀、装饰。
  4. 装饰者模式的设计原则为:对扩展开放、对修改关闭,这句话体现在我如果想扩展被装饰者类的行为,无须修改装饰者抽象类,只需继承装饰者抽象类,实现额外的一些装饰或者叫行为即可对被装饰者进行包装。所以:扩展体现在继承、修改体现在子类中,而不是具体的抽象类,这充分体现了依赖倒置原则,这是自己理解的装饰者模式。

四. 代理模式----(为别人做嫁衣)

定义:为其他对象提供一种代理以控制对这个对象的访问。
使用场景:当无法或者不想直接访问某一个对象时,可以通过一个代理对象来间接访问,为了委托客户端使用的透明性,委托对象与代理对象需要实现同一个接口。
  • 例:小民委托律师要回自己的工资
  • 接口类
public interface ILawsuit {//提交申请void submit();//进行举证void burden();//开始辩护void defend();//诉讼完成void finish();
}
  • 委托人
public class XiaoMin implements ILawsuit {@Overridepublic void submit() {System.out.println("老板拖欠工资!因此申请仲裁!");}@Overridepublic void burden() {System.out.println("这是合同书和过去一年银行的流水账单!");}@Overridepublic void defend() {System.out.println("证据确凿,不用再多说了!");}@Overridepublic void finish() {System.out.println("诉讼成功!马上发工资");}
}
  • 代理律师
public class Lawyer implements ILawsuit {private ILawsuit iLawsuit;public Lawyer(ILawsuit iLawsuit) {this.iLawsuit = iLawsuit;}@Overridepublic void submit() {iLawsuit.submit();}@Overridepublic void burden() {iLawsuit.burden();}@Overridepublic void defend() {iLawsuit.defend();}@Overridepublic void finish() {iLawsuit.finish();}
}
  • 开庭审理的客户类
public class Client {public static void main(String[] args){XiaoMin xiaoMin = new XiaoMin();ILawsuit iLawsuit = new Lawyer(xiaoMin);//律师开始替小民打官司iLawsuit.submit();iLawsuit.burden();iLawsuit.defend();iLawsuit.finish();}
}

五. 工厂模式:

定义:定义一个用于创建对象的接口,让子类决定实例化哪个类。
使用场景:在任何需要生成复杂对象的地方,都可以使用工厂方法模式。复杂对象适合使用工厂模式,用new 就可以完成的对象无需使用工厂模式。

优点:克服了简单工厂违背的开放-封闭原则的缺点,又保持了封装对象创建过程的优点。
缺点:每次为工厂方法添加新的产品的时候就要编写一个新的产品类。在android中,onCreat()使用的即是该模式,还有java中的list和Set集合,都是这种模式
  • 定义一个抽象产品类
public abstract class Product {/*** 产品类的抽象方法,由具体的产品类去实现*/public abstract void method();
}
  • 具体的产品实现类
public class ConcreteProductA extends Product {@Overridepublic void method() {System.out.println("我是具体的产品A");}
}public class ConcreteProductB extends Product {@Overridepublic void method() {System.out.println("我是具体的产品B");}
}
  • 抽象工厂类
public abstract class Factory {/*** 抽象工厂方法,具体生产什么由子类去实现** @param clz 产品对象类型* @param <T> 具体的产品对象* @return*/public abstract <T extends Product> T createProduct(Class<T> clz);
}
  • 具体的工厂类,通过反射获取类的事例即可
public class ConcreteFactory extends Factory {@Overridepublic <T extends Product> T createProduct(Class<T> clz) {Product product = null;try {product = (Product) Class.forName(clz.getName()).newInstance();} catch (Exception e) {e.printStackTrace();}return (T) product;}
}
  • 客户端中具体的实现
public class Client {public static void main(String[] args) {Factory factory = new ConcreteFactory();Product product = factory.createProduct(ConcreteProductA.class);//需要什么就传什么product.method();}
}

六. 原型模式 (Intent 等)

用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。
  1. 实现CLoneable接口。作用是在运行时通知虚拟机可以安全的实现了此接口的类上使用clone方法。
  2. 重写Object类中的clone方法。Java中,所有类的父类都是Object类,Object类中有一个clone方法,作用是返回对象的一个拷贝,但是其作用域protected类型的,一般的类无法调用,因此,Prototype类需要将clone方法的作用域修改为public类型

注意: 只有当通过new 构造对象较为耗时间或者说成本比较高的时候,通过clone方法才能获得效率上的提升。

举例: 复制简历想要修改的问题
  • 原型类:
public class Prototype implements Cloneable {  private ArrayList list = new ArrayList();  public Prototype clone(){  Prototype prototype = null;  try{  prototype = (Prototype)super.clone();  prototype.list = (ArrayList) this.list.clone();  //引用类型的必须都要用深引用}catch(CloneNotSupportedException e){  e.printStackTrace();  }  return prototype;   }
}
  • 原型实现类
class ConcretePrototype extends Prototype{  public void show(){  System.out.println("原型模式实现类");  }
}
  • 客户端执行
public class Client {  public static void main(String[] args){  ConcretePrototype cp = new ConcretePrototype();  for(int i=0; i< 10; i++){  ConcretePrototype clonecp = (ConcretePrototype)cp.clone();  clonecp.show();  }  }
}

七. 模版模式:

定义一个操作中的算法框架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重定义该算法得某些特定步骤。
  • 使用场景
  1. 多个子类公有得方法,并且逻辑基本相同时。

  2. 重要、复杂的算法,可以把核心设计为模版方法,周边的相关细节功能则由各个子类实现。

  3. 重构时,模版方法模式是一个经常使用的模版,把相同的代码抽取到父类中,然后通过子函数约束其行为。

    总结:就是封装流程。也就是把某个固定的流程封装到一个final函数中,并且让子类能够制定这个流程中的某些或所有步骤,
    这就要求父类提取共用的代码,提升代码的复用率,同时也带来了很好的可扩展性。
    优点:
    1.封装不变的部分,变成可变部分
    2.提取公告部分代码,便于维护。
    缺点:
    模版方法会带来代码阅读的难度,会让用户感觉难以理解。

  • 封装流程代码:
public abstract class AbstractComputer {protected void powerOn() {System.out.println("开启电源");}protected void checkHardware() {System.out.println("硬件检查");}protected void loadOs() {System.out.println("载入操作系统");}protected void login() {System.out.println("小白的计算机无需验证,直接登陆");}public final void startUp(){System.out.println("----------------开机start--------------");powerOn();checkHardware();loadOs();login();System.out.println("----------------关机End--------------");}
}
  • 具体流程改变(程序员电脑类)
public class CodeComputer extends AbstractComputer {@Overrideprotected void login() {//        注意:此处省略了super
//        super.login();System.out.print("程序员的电脑只需要用户和密码的验证就行");}
}
  • 具体流程改变(军事使用电脑类)
public class MilitaryComputer extends AbstractComputer {@Overrideprotected void checkHardware() {super.checkHardware();System.out.println("检查硬件防火墙");}@Overrideprotected void login() {System.out.println("进行指纹识别等复杂的用户实验");}
}
  • 测试使用
public class Test {public static void main(String[] args){AbstractComputer abstractComputer = new CodeComputer();abstractComputer.startUp();abstractComputer = new MilitaryComputer();abstractComputer.startUp();}
}
//输出结果如下:
//    ----------开机start-----------
//    开启电源
//    硬件检查
//    载入操作系统
//    程序员的电脑只需要用户和密码的验证就行
//    ----------------关机End--------------
//    ----------开机start-----------
//    开启电源
//    硬件检查
//    检查硬件防火墙
//    载入操作系统
//    进行指纹识别等复杂的用户实验
//    ----------------关机End--------------

八. Builder模式

将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
  • 使用场景

    1. 相同的方法,不同的执行顺序,产生不同的事件结果时。
    2. 多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同。
    3. 产品类非常复杂,或者产品类中的调用顺序不同产生了不同的作用,这个时候使用建造者模式非常合适。
    4. 当初始化一个对象非常复杂,如参数多,且很多参数都有默认值的时候。
//计算机抽象类,即product角色
public abstract class Computer {protected String mBoard;protected String mDisplay;protected String mOs;public Computer() {}//设置CPU核心数public void setmBoard(String mBoard) {this.mBoard = mBoard;}//设置内存public String getmDisplay() {return mDisplay;}//设置操作系统public void setmDisplay(String mDisplay) {this.mDisplay = mDisplay;}public abstract void setmOs();@Overridepublic String toString() {return "Computer{" +"mBoard='" + mBoard + '\'' +", mDisplay='" + mDisplay + '\'' +", mOs='" + mOs + '\'' +'}';}
}//具体的Computer类
public class Macbook extends Computer {public Macbook() {}@Overridepublic void setmOs() {mOs = "Mac OS X 10.10";}
}//抽象类
public abstract class Builder {//设置主机public abstract void buildBoard(String board);//设置显示器public abstract void buildDisplay(String display);//设置操作系统public abstract void buildOS();//创建Computerpublic abstract Computer create();
}//具体的builder类
public class MacbookBuilder extends Builder {private Computer computer = new Macbook();@Overridepublic void buildBoard(String board) {computer.setmBoard(board);}@Overridepublic void buildDisplay(String display) {computer.setmDisplay(display);}@Overridepublic void buildOS() {computer.setmOs();}@Overridepublic Computer create() {return computer;}
}//负责构造Computer,在实际使用中,常常被忽略掉
public class Director {Builder builder = null;public Director(Builder builder) {this.builder = builder;}public void construct(String board,String display){builder.buildBoard(board);builder.buildDisplay(display);builder.buildOS();}
}//测试类
public class Test {public static void main(String[] args) {Builder builder = new MacbookBuilder();Director director = new Director(builder);director.construct("inter的主板", "Retina显示器");System.out.println("Computer Info : " + builder.create().toString());}
}

九:抽象工厂模式

  • 简单代码实现
  1. 定义抽象工厂类
    public abstract class CarFactory {/*** 生产轮胎* @return 轮胎*/public abstract ITire createTire();/*** 生产发动机* @return 发动机*/public abstract IEngine createEngine();/*** 生产制动系统* @return 制动系统*/public abstract IBreak createBreak();
}
  1. 各个细节的抽象
public interface ITire {/*** 轮胎*/void tire();
}public interface IEngine {/*** 发动机*/void engine();
}public interface IBreak {/*** 制动* */void bradk();
}
  1. 具体细节的实现
public class NormalTire implements ITire {@Overridepublic void tire() {System.out.println("普通轮胎");}
}public class SuvTire implements ITire {@Overridepublic void tire() {System.out.println("SUV轮胎");}
}public class DomesticEngine implements IEngine {@Overridepublic void engine() {System.out.print("国产发动机");}
}public class ImportEngine implements IEngine {@Overridepublic void engine() {System.out.print("进口发动机");}
}public class NormalBrake implements IBreak {@Overridepublic void bradk() {System.out.print("普通制动");}
}public class SeniorBrake implements IBreak {@Overridepublic void bradk() {System.out.print("高级制动");}
}
  1. 具体实现

public class Q3Factory extends CarFactory {@Overridepublic ITire createTire() {return new NormalTire();}@Overridepublic IEngine vreateEngine() {return new DomesticEngine();}@Overridepublic IBreak iBreak() {return new NormalBrake();}
}public class Q7Factory extends CarFactory {@Overridepublic ITire createTire() {return new SuvTire();}@Overridepublic IEngine vreateEngine() {return new ImportEngine();}@Overridepublic IBreak iBreak() {return new SeniorBrake();}
}
  1. 客户端的实现
public class Client {public static void main(String[] args) {CarFactory factoryQ3 = new Q3Factory();factoryQ3.createTire().tire();factoryQ3.createEngine().engine();factoryQ3.createBreak().bradk();System.out.println("------------------");CarFactory factoryQ7 = new Q7Factory();factoryQ7.createTire().tire();factoryQ7.createEngine().engine();factoryQ7.createBreak().bradk();}
}

十:状态模式(电视遥控器)(开关Wi-Fi等等)

定义:当一个对象的内在状态改变的时允许改变起行为,这个对象看起来像是改变了其类。
使用场景:1. 一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为。2.代码中包含大量与对象状态有关的条件语句,例如,一个操作中含有庞大的多分支语句(if-else或switch-case),且这些分支依赖于该对象的状态。
优点:通过多态的形式减少那些重复的判断语句,增强了可扩展性,灵活性。
缺点:必然会增加系统类和对象的个数。
//电视状态
public interface TvState {void nextChannel();void prevChannel();void tureUp();void turnDown();
}public class PowerOnState implements TvState {@Overridepublic void nextChannel() {System.out.println("下一频道");}@Overridepublic void prevChannel() {System.out.println("上一频道");}@Overridepublic void tureUp() {System.out.println("调高音量");}@Overridepublic void turnDown() {System.out.println("调低音量");}
}
//关机后的操作
public class PowerOffState implements TvState {@Overridepublic void nextChannel() {}@Overridepublic void prevChannel() {}@Overridepublic void tureUp() {}@Overridepublic void turnDown() {}
}
//设置两种状态
public interface PowerController {void powerOn();void powerOff();
}
//遥控器
public class TvController implements PowerController {TvState mTvState;public void setmTvState(TvState mTvState) {this.mTvState = mTvState;}@Overridepublic void powerOn() {setmTvState(new PowerOnState());}@Overridepublic void powerOff() {setmTvState(new PowerOffState());}public void nextChannel(){mTvState.nextChannel();}public void preChannel(){mTvState.prevChannel();}public void turnUp(){mTvState.tureUp();}
}public class Client {public static void main(String[] args) {TvController tvController = new TvController();//设置开机状态tvController.powerOn();//下一频道tvController.nextChannel();//调高音量tvController.turnUp();//设置关机状态tvController.powerOff();//调高音量,此时不会生效tvController.turnUp();}
}

十一:观察者模式

定义:定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。使用场景:1.关联行为场景,需要注意的是,关联行为是可拆分的,而不是“组合”关系;2.事件多级触发场景;3.跨系统的消息交换场景,如消息队列、事件总线的处理机制。
//程序员是观察者
public class Coder implements Observer {public String name;public Coder(String name) {this.name = name;}@Overridepublic void update(Observable observable, Object data) {System.out.println("Hi,  " + name + "新内容来啦");}@Overridepublic String toString() {return "码农 : " + name;}
}//被观察者,当它有更新的时候,所有的观察者(这里是Coder)都会接到相应的通知
public class NewContent extends Observable {public void postNewPublication(String content){//标示状态或者内容发生改变setChanged();//通知所有的观察者notifyObservers(content);}
}public class Client {public static void main(String[] args){//被观察的对象NewContent newContent = new NewContent();//观察者Coder coder  = new Coder("mr.simple");Coder coder1 = new Coder("coder-1");Coder coder2 = new Coder("coder-2");Coder coder3 = new Coder("coder-3");//将观察者注册到可观察对象的观察列表中newContent.addObserver(coder);newContent.addObserver(coder1);newContent.addObserver(coder2);newContent.addObserver(coder3);//发布消息newContent.postNewPublication("新的一期开发技术周报发布啦!!!");}
}

十二:适配器模式(姚明去NBA打篮球需要翻译)

定义:适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。使用场景:1.系统需要使用现在的类,而此类的接口不符合系统的需要,即接口不兼容。2.想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。3.需要一个统一的输出接口,而输入端的类型不可预知。
//球员踢球
public abstract class Player {protected String name;public Player(String name) {this.name = name;}public abstract void attack();public abstract void defense();
}//前锋
public class Forwards extends Player {public Forwards(String name) {super(name);}@Overridepublic void attack() {System.out.println("前锋  进攻---->>>" + name);}@Overridepublic void defense() {System.out.println("前锋  防守---->>>" + name);}
}//后卫
public class Center extends Player {public Center(String name) {super(name);}@Overridepublic void attack() {System.out.println("后卫  进攻---->>>" + name);}@Overridepublic void defense() {System.out.println("后卫  防守---->>>" + name);}
}//外籍中锋
public class ForeignCenter {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}public void 进攻() {System.out.println("外籍中锋  进攻" + name);}public void 防守() {System.out.println("外籍中锋  防守" + name);}
}//翻译者
public class Translator extends Player {private ForeignCenter wjzf = new ForeignCenter();public Translator(String name) {super(name);wjzf.setName(name);}@Overridepublic void attack() {wjzf.进攻();}@Overridepublic void defense() {wjzf.防守();}
}//客户端
public class Client {public static void main(String[] args) {Player b = new Forwards("巴蒂尔");b.attack();Player m = new Center("麦克");m.attack();Player ym = new Translator("姚明");ym.attack();ym.defense();}
}

十三:备忘录模式

定义:在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样,以后就可将该对象恢复到原先保存的状态。
应用场景:1.需要保存一个对象在某一个时刻的状态或部分状态。2.如果用一个接口来让其他对象得到这些状态,将会暴漏对象的实现细节并破坏对象的封装性,一个对象不希望外界直接访问其内部状态,通过中间对象可以间接访问其内部状态。
//备忘录类
public class Memoto {public int mCheckPoint;public int mLifeValue;public String mWeapon;@Overridepublic String toString() {return "Memoto{" +"mCheckPoint=" + mCheckPoint +", mLifeValue=" + mLifeValue +", mWeapon='" + mWeapon + '\'' +'}';}
}//游戏
public class CallOfDuty {private int mCheckPoint = 1;private int mLifeValue = 100;private String mWeapon = "沙漠之鹰";//玩游戏public void play() {System.out.println("玩游戏 : " + String.format("第%d关", mCheckPoint) + "奋战杀敌中");mLifeValue -= 10;System.out.println("进度升级啦");mCheckPoint++;System.out.println("到达 : " + String.format("第%d关", mCheckPoint) + "奋战杀敌中");}//退出游戏public void quit() {System.out.println("-----------------");System.out.println("退出前的游戏属性 : " + this.toString());System.out.println("退出游戏");System.out.println("-----------------");}//创建备忘录public Memoto creatMemoto() {Memoto memoto = new Memoto();memoto.mCheckPoint = mCheckPoint;memoto.mLifeValue = mLifeValue;memoto.mWeapon = mWeapon;return memoto;}//恢复游戏public void restore(Memoto memoto) {this.mCheckPoint = memoto.mCheckPoint;this.mLifeValue = memoto.mLifeValue;this.mWeapon = memoto.mWeapon;System.out.println("回复后的游戏属性 : " + this.toString());}//TODO 省略了get 和 set 方法@Overridepublic String toString() {return "CallOfDuty{" +"mCheckPoint=" + mCheckPoint +", mLifeValue=" + mLifeValue +", mWeapon='" + mWeapon + '\'' +'}';}
}// 管理类
public class Caretaker {Memoto memoto;//存档public void archive(Memoto memoto) {this.memoto = memoto;}//获取存档public Memoto getMemoto() {return memoto;}
}public class Client {public static void main(String[] args) {//构建游戏对象CallOfDuty game = new CallOfDuty();//开始游戏game.play();Caretaker caretaker = new Caretaker();//游戏存档caretaker.archive(game.creatMemoto());//退出游戏game.quit();//恢复游戏CallOfDuty newGame = new CallOfDuty();newGame.restore(caretaker.getMemoto());}
}

十四: 组合模式(View 和ViewGroup),公司故事

定义: 将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象使用的一致性。使用场景:1.表示对象的部分-整体层次结构时。2.从一个整体中能够独立出部分模块或功能的场景。
//公司类
public abstract class Company {protected String name;public Company(String name) {this.name = name;}public abstract void add(Company c);//增加public abstract void remove(Company c);//移除
}//分级组合
public class ConcreteCompany extends Company {private List<Company> children = new ArrayList<>();public ConcreteCompany(String name) {super(name);}@Overridepublic void add(Company c) {children.add(c);}@Overridepublic void remove(Company c) {children.remove(c);}
}//财务类
public class FinanceDepartment extends Company {public FinanceDepartment(String name) {super(name);}@Overridepublic void add(Company c) {}@Overridepublic void remove(Company c) {}
}//人事部
public class HRDepartment extends Company {public HRDepartment(String name) {super(name);}@Overridepublic void add(Company c) {}@Overridepublic void remove(Company c) {}
}//客户端
public class Client {public static void main(String[] args) {ConcreteCompany root = new ConcreteCompany("北京总公司");root.add(new HRDepartment("总公司人力资源部"));root.add(new FinanceDepartment("总公司财务部"));ConcreteCompany comp = new ConcreteCompany("上海分公司");comp.add(new HRDepartment("上海分公司人力资源部"));comp.add(new FinanceDepartment("上海分公司财务部"));root.add(comp);ConcreteCompany comp1 = new ConcreteCompany("南京办事处");comp1.add(new HRDepartment("南京办事处人力资源部"));comp1.add(new FinanceDepartment("南京办事处财务部"));comp.add(comp1);}
}

十五:迭代器模式

定义:提供一种方法顺序访问一个容器对象中的各个元素,而又不需要暴漏该对象的内部显示。使用场景:遍历一个容器对象时。
public interface Iterator {//是否还有下一个元素  true 表示有,false 表示没有boolean hasNext();//返回当前位置的元素,并将位置移至下一位Object next();
}//查询信息的类
public class Employee {private String name;private int age;private String sex;private String position;public Employee(String name, int age, String sex, String position) {this.name = name;this.age = age;this.sex = sex;this.position = position;}@Overridepublic String toString() {return "Employee{" +"name='" + name + '\'' +", age=" + age +", sex='" + sex + '\'' +", position='" + position + '\'' +'}';}
}public class MinIterator implements Iterator {private List<Employee> list;private int position;public MinIterator(List<Employee> list) {this.list = list;}@Overridepublic boolean hasNext() {return !(position > list.size() - 1 || list.get(position) == null);}@Overridepublic Object next() {Employee employee = list.get(position);position++;return employee;}
}//和MinIterator 是两种不同的查询方式
public class HuiIterator implements Iterator {private Employee[] array;private int position;public HuiIterator(Employee[] array) {this.array = array;}@Overridepublic boolean hasNext() {return !(position > array.length - 1 || array[position] == null);}@Overridepublic Object next() {Employee employee = array[position];position++;return employee;}
}public interface Company {//返回一个迭代器对象Iterator iterator();
}public class CompanyHui implements Company {private Employee[] array = new Employee[3];public CompanyHui() {array[0] = new Employee("辉哥", 108, "男", "程序员");array[1] = new Employee("小红", 98, "男", "程序员");array[2] = new Employee("小晴", 102, "男", "程序员");}@Overridepublic Iterator iterator() {return new HuiIterator(array);}public Employee[] getEmployees() {return array;}
}
public class CompanyMIn implements Company {private List<Employee> list = new ArrayList<>();public CompanyMIn() {list.add(new Employee("小民", 92, "男", "程序员"));list.add(new Employee("小芳", 22, "女", "测试"));list.add(new Employee("小可", 23, "女", "测试"));list.add(new Employee("小朗", 20, "男", "设计"));}public List<Employee> getEmployees() {return list;}@Overridepublic Iterator iterator() {return new MinIterator(list);}
}//当Boss查询的时候,就只需查询就可
public class Boss {public static void main(String[] args) {CompanyMIn companyMIn = new CompanyMIn();check(companyMIn.iterator());CompanyHui companyHui = new CompanyHui();check(companyHui.iterator());}private static void check(Iterator iterator) {while (iterator.hasNext()) {System.out.println(iterator.next().toString());}}
}

十六:单例模式。

懒汉模式

//懒汉模式是声明一个静态对象,并且在用户第一次调用getInstance时进行初始化
public class Signleton {private static Signleton instance;private Signleton() {}//进行同步,造成不必要的同步开销。不推荐这种方法。public static synchronized Signleton getInstance() {if (instance == null) {instance = new Signleton();}return instance;}
}

Double Check Lock (DCL) 实现单例,

public class Signleton {private static Signleton instance = null;private Signleton() {}/***  优点:既能够在需要时才初始化单例,又能保证线程安全*  缺点:由于java内存模型的原因(乱序执行)偶尔会失败*/public static Signleton getInstance() {if (instance == null) {//避免不必要的同步synchronized (Signleton.class){if (instance == null){//在instance为null的情况下创建实例instance = new Signleton();}}}return instance;}
}--由于jvm的特性,允许乱序执行,所以上面的DCL的执行顺序不定,就有可能出现DCL失效的问题。
为了解决这一问题,java1.6开始加入volatile关键字
private volatile static Signleton instance.
这种情况就避免了DCL方法失效,但是volatile消耗一些性能//推荐使用方法 ,静态内部类方式,确保线程安全,保证单例唯一
//第一次加载的时候并不会初始化sInstance,只有在第一次调用Singleton的getInstance方法时才会导致初始化。
public class Signleton {private Signleton() {}public static Signleton getInstance() {return SingletonHolder.sInstance;}private static class SingletonHolder {private static final Signleton sInstance = new Signleton();}
}

十七: 桥接模式

定义:将抽象部分与实现部分分离,使它们都可以独立的进行变化。使用场景:一个类存在两个独立变化的纬度,且这两个纬度都需要进行扩展。
public abstract class CoffeeAdditivies {/*** 具体要往咖啡里添加什么也是由子类实现* @return 具体添加的东西*/public abstract String addSomething();
}public class Ordinary extends CoffeeAdditivies {@Overridepublic String addSomething() {return "原味";}
}public class Sugar extends CoffeeAdditivies {@Overridepublic String addSomething() {return "加糖";}
}public abstract class Coffee {protected CoffeeAdditivies impl;public Coffee(CoffeeAdditivies impl) {this.impl = impl;}/*** 咖啡具体是什么样的由子类决定*/public abstract void makeCoffee();
}public class LarrgeCoffee extends Coffee {public LarrgeCoffee(CoffeeAdditivies impl) {super(impl);}@Overridepublic void makeCoffee() {System.out.println("大杯的" + impl + "咖啡");}
}public class SmallCoffee extends Coffee {public SmallCoffee(CoffeeAdditivies impl) {super(impl);}@Overridepublic void makeCoffee() {System.out.println("小杯的 " + impl + "咖啡");}
}public class Client {public static void main(String[] args) {//原汁原味Ordinary impOrdinary = new Ordinary();//准备加糖Sugar implSugar = new Sugar();//大杯咖啡 原味LarrgeCoffee larrgeCoffee = new LarrgeCoffee(impOrdinary);larrgeCoffee.makeCoffee();//小杯咖啡 加糖SmallCoffee smallCoffee = new SmallCoffee(implSugar);smallCoffee.makeCoffee();}
}

十八: 命令模式 (几乎体现了设计模式的所有的通病,就是类的膨胀)

定义:讲一个请求封装成一个对象,从而让用户使用不同的请求把客户端参数化;对请求拍队或者记录请求日志,以及支持可撤销的操作。使用场景:1. 需要支持取消操作。2. 支持修改日志功能,这样当系统崩溃时,这些修改可以重做一遍。3. 需要支持事物操作。
//接受者角色
public class TetrisMachine {public void toLeft(){System.out.println("向左");}public void toRight(){System.out.println("向右");}
}//命令者抽象  定义执行方法
public interface Command {void execute();
}public class LeftCommand implements Command {private TetrisMachine tetrisMachine;public LeftCommand(TetrisMachine tetrisMachine) {this.tetrisMachine = tetrisMachine;}@Overridepublic void execute() {tetrisMachine.toLeft();}
}public class RightCommand implements Command {private TetrisMachine tetrisMachine;public RightCommand(TetrisMachine tetrisMachine) {this.tetrisMachine = tetrisMachine;}@Overridepublic void execute() {tetrisMachine.toRight();}
}public class Button {private LeftCommand leftCommand;private RightCommand rightCommand;public void setLeftCommand(LeftCommand leftCommand) {this.leftCommand = leftCommand;}public void setRightCommand(RightCommand rightCommand) {this.rightCommand = rightCommand;}public void toLeft() {leftCommand.execute();}public void toRight() {rightCommand.execute();}
}public class Client {public static void main(String[] args) {TetrisMachine tetrisMachine = new TetrisMachine();//根据游戏我们构造4种命令LeftCommand leftCommand = new LeftCommand(tetrisMachine);RightCommand rightCommand = new RightCommand(tetrisMachine);//按钮可以执行不同的命令Button button = new Button();button.setLeftCommand(leftCommand);button.setRightCommand(rightCommand);//具体按下哪个,玩家说了算button.toLeft();button.toRight();}
}

敏捷开发原则告诉我们,不要为代码添加基于猜测的,实际不需要的功能,如果不清楚一个系统是否需要命令模式,一般就不要着急去实现它。

可以直接实现:public class Client {public static void main(String[] args) {TetrisMachine tetrisMachine = new TetrisMachine();tetrisMachine.toLeft();tetrisMachine.toRight();}
}

十九: 责任链模式:

定义:使多个对象都有机会处理请求,从而避免来请求的发送者和接收者之间的耦合关系。将这些对象连城一条链,并沿着这条链传递该请求,只到有对象处理它为止。使用场景:1. 多个对象可以处理同一请求,但具体由哪个对象处理则在运行时动态决定。2. 在请求处理者不明确的情况下向多个对象中的一个提交一个请求。3. 需要动态指定一组对象处理请求。
public abstract class Leader {protected Leader nextHandler;//上一级领导处理者/** 处理报账请求* */public final void handleRequest(int money) {if (money < limit()) {handle(money);} else {if (null != nextHandler) {nextHandler.handleRequest(money);}}}/*** 自身能批复的额度权限*/public abstract int limit();/*** 处理报账行为*/public abstract void handle(int money);
}public class GroupLeader extends Leader {@Overridepublic int limit() {return 1000;}@Overridepublic void handle(int money) {System.out.println("组长批复报销" + money + "元");}
}public class Director extends Leader {@Overridepublic int limit() {return 5000;}@Overridepublic void handle(int money) {System.out.println("主管批复报销" + money + "元");}
}public class Boss extends Leader {@Overridepublic int limit() {return Integer.MAX_VALUE;}@Overridepublic void handle(int money) {System.out.println("老板批复报销" + money + "元");}
}public class Client {public static void main(String[] args) {GroupLeader groupLeader = new GroupLeader();Director director = new Director();Boss boss = new Boss();//设置上一级领导处理者对象groupLeader.nextHandler = director;director.nextHandler = boss;//发起账单申请groupLeader.handleRequest(20000);}
}

二十: 中介者模式

定义: 用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显示地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。使用场景:1.当对象之间的交互操作很多且每个对象的行为操作都依赖彼此时,为防止在修改一对象的行为时,同时设计修改很多其他对象的行为,可采用中介者模式。
// 抽象同事类
public class Colleague {protected Mediator mediator;public Colleague(Mediator mediator) {this.mediator = mediator;}
}public class ConcreteColleague1 extends Colleague {public ConcreteColleague1(Mediator mediator) {super(mediator);}public void send(String message) {mediator.send(message, this);}public void notify(String message) {System.out.println("同事1得到消息:" + message);}
}public class ConcreteColleague2 extends Colleague {public ConcreteColleague2(Mediator mediator) {super(mediator);}public void send(String message) {mediator.send(message, this);}public void notify(String message) {System.out.println("同事2得到消息: " + message);}
}// 抽象中介者
public abstract class Mediator {/*** 同事对象改变时通知中介者方法* 在同事对象改变时由中介者去通知其他的同事对象*/public abstract void send(String message,Colleague collegue);
}// 具体的中介者类
public class ConcreteMediator extends Mediator {private ConcreteColleague1 concreteColleague1;private ConcreteColleague2 concreteColleague2;public void setConcreteColleague1(ConcreteColleague1 concreteColleague1) {this.concreteColleague1 = concreteColleague1;}public void setConcreteColleague2(ConcreteColleague2 concreteColleague2) {this.concreteColleague2 = concreteColleague2;}@Overridepublic void send(String message, Colleague collegue) {if (collegue == concreteColleague1) {concreteColleague2.notify();} else {concreteColleague1.notify();}}
}public class Client {public static void main(String[] args) {ConcreteMediator concreteMediator = new ConcreteMediator();ConcreteColleague1 concreteColleague1 = new ConcreteColleague1(concreteMediator);ConcreteColleague2 concreteColleague2 = new ConcreteColleague2(concreteMediator);concreteMediator.setConcreteColleague1(concreteColleague1);concreteMediator.setConcreteColleague2(concreteColleague2);concreteColleague1.send("吃过饭没有");concreteColleague2.send("没有呢,你打算请客吗?");}
}

二十一:解释器模式

定义:当有一个语言需要解释执行,并且你可将该语言中的句子表示为一个抽象的语法树时,可使用解释器模式。
//解释器共性的提取
public abstract class ArithmeticExpression {//抽象的解析方法,具体的解析逻辑由具体的子类的实现public abstract int interpret();
}public class NumExpression extends ArithmeticExpression {private int num;public NumExpression(int num) {this.num = num;}@Overridepublic int interpret() {return num;}
}public class OperatorExpression extends ArithmeticExpression {protected ArithmeticExpression expression1,expression2;public OperatorExpression(ArithmeticExpression expression1, ArithmeticExpression expression2) {this.expression1 = expression1;this.expression2 = expression2;}@Overridepublic int interpret() {return 0;}
}public class AdditionExpression extends OperatorExpression {public AdditionExpression(ArithmeticExpression expression1, ArithmeticExpression expression2) {super(expression1, expression2);}@Overridepublic int interpret() {return expression1.interpret() + expression2.interpret();}
}//处理和解释相关的一些业务
public class Calculator {private Stack<ArithmeticExpression> mExpStack = new Stack<ArithmeticExpression>();public Calculator(String expression) {ArithmeticExpression expression1, expression2;String[] elements = expression.split(" ");for (int i = 0; i < elements.length; i++) {switch (elements[i].charAt(0)) {case '+'://则将栈中的解释器弹出作为运算符号左边的解释器expression1 = mExpStack.pop();//同时将运算符号数组下标一个下一个元素构成为一个数字解释器expression2 = new NumExpression(Integer.valueOf(elements[++i]));//通过上面两个数字解释器构造加法运算解释器mExpStack.push(new AdditionExpression(expression1, expression2));break;default://如果为数字mExpStack.push(new NumExpression(Integer.valueOf(elements[i])));break;}}}public int calculate() {return mExpStack.pop().interpret();}
}public class Client {public static void main(String[] args) {Calculator calculator = new Calculator("153 + 3589 + 118 + 555");System.out.println(calculator.calculate());}
}

二十二:访问者模式

定义:封装一些作用于某种数据结构中的各元素的操作,它可以在不改变这个数据结构的前提下定义作用于这些元素的新的操作。使用场景:1.对象结构比较稳定,但经常需要在此对象结构上定义新的操作。2.需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免这些操作“污染”这些对象的类,也不希望在增加新操作时修改这些类。
public interface Visitor {//访问工程师类型public void visit(Engineer engineer);//访问经理类型public void visit(Manager leader);
}public class CEOVisitor implements Visitor {@Overridepublic void visit(Engineer engineer) {System.out.println("工程师 : " + engineer.name + ",KPI : " + engineer.kpi);}@Overridepublic void visit(Manager leader) {System.out.println("工程师 : " + leader.name + ",KPI : " + leader.kpi + ",新产品数量 : " + leader.getProducts());}
}public class CTOVisitor implements Visitor {@Overridepublic void visit(Engineer engineer) {System.out.println("工程师 : " + engineer.name + "代码函数 : " + engineer.getCodeLines());}@Overridepublic void visit(Manager leader) {System.out.println("经理 : " + leader.name + "产品数量 : " + leader.getProducts());}
}public abstract class Staff {public String name;public int kpi;public Staff(String name) {this.name = name;}public abstract void accept(Visitor visitor);
}public class Engineer extends Staff {public Engineer(String name) {super(name);}@Overridepublic void accept(Visitor visitor) {visitor.visit(this);}// 工程师一年写的代码量public int getCodeLines() {return new Random().nextInt(10 * 10000);}
}public class Manager extends Staff{private int products;public Manager(String name) {super(name);products = new Random().nextInt(10);}@Overridepublic void accept(Visitor visitor) {visitor.visit(this);}//一年内做的产品数量public int getProducts(){return products;}
}public class BusinessReport {List<Staff> mStaffs = new LinkedList<>();public BusinessReport() {mStaffs.add(new Manager("王经理"));mStaffs.add(new Engineer("工程师-小王"));mStaffs.add(new Engineer("工程师-小李"));mStaffs.add(new Engineer("工程师-小张"));}public void showReport(Visitor visitor){for (Staff staff : mStaffs){staff.accept(visitor);}}
}public class Client {public static void main(String[] args) {BusinessReport report = new BusinessReport();System.out.println("=========== 给CEO看的报表 ===========");//设置访问者,这里是CEOreport.showReport(new CEOVisitor());System.out.println("=========== 给CTO看的报表 ===========");//注入另一个访问者,CTOreport.showReport(new CTOVisitor());}
}public class ReportUitl {public void visit(Staff staff){if (staff instanceof Manager ){Manager manager = (Manager) staff;System.out.println("经理 : "+ manager.name + ",KPI : "+ manager.kpi + ",新产品数量 : "+manager.getProducts());}else {Engineer engineer = (Engineer) staff;System.out.println("工程师 : "+ engineer.name + ",KPI : "+ engineer.kpi );}}
}

设计模式读书笔记汇总相关推荐

  1. 大话设计模式读书笔记

    主题 概要 设计模式 大话设计模式读书笔记 编辑 时间 新建 20170423 序号 参考资料 1 大话设计模式 重新看了一遍设计模式,除了一些已经特别熟悉的模式,都自己敲了一遍代码,有些豁然开朗的感 ...

  2. JavaScript设计模式读书笔记(一)= 创建型设计模式

    全系列目录 JavaScript设计模式读书笔记(一)=> 创建型设计模式 JavaScript设计模式读书笔记(二)=> 结构型设计模式 JavaScript设计模式读书笔记(三)=&g ...

  3. JavaScript设计模式读书笔记(四)= 技巧型设计模式

    全系列目录 JavaScript设计模式读书笔记(一)=> 创建型设计模式 JavaScript设计模式读书笔记(二)=> 结构型设计模式 JavaScript设计模式读书笔记(三)=&g ...

  4. 金融市场基础知识-全书读书笔记汇总

    金融市场基础知识-全书读书笔记汇总 参考: https://mp.weixin.qq.com/s?__biz=MzUxNDc2ODk1Mw==&mid=2247484311&idx=1 ...

  5. 设计模式读书笔记-----工厂方法模式

    一.问题 在前一章<设计模式读书笔记-----简单工厂模式>中通过披萨的实例介绍了简单工厂模式.在披萨实例中,如果我想根据地域的不同生产出不同口味的披萨,如纽约口味披萨,芝加哥口味披萨.如 ...

  6. 《浪潮之巅》读书笔记汇总

    其实我是没有做读书笔记的习惯的,但是这本书只是借来看的,而且这种杂谈性的书,也比较容易扯开去,就随便写了一些东西,大多是自己的一些乱七八糟的想法.现在给汇总一下发出来把.. 1. 第一章 AT& ...

  7. 设计模式---读书笔记

    一.文章来由 按照惯例,来一个来由,这是<设计模式-可复用面向对象软件的基础>的读书笔记,整理给自己看的,整理的内容也会不断更新.大神轻喷~~如果不喜欢请留言说明原因再踩哦,谢谢,我也可以 ...

  8. 《统计学习方法》-读书笔记汇总贴(汇总27/27)

    本人学习所有系列:汇总帖 文章主要用来记录学习李航老师<统计学习方法(第二版)>的学习笔记,主要根据课本内容来,初步打算按照章节目录将知识点慢慢整理,希望能互相学习,共同提高! 目录 第1 ...

  9. 设计模式学习笔记汇总目录

    这里的学习笔记包含JavaSE和J2EE两部分,持续更新中! 其中关于学习的参考资料如下: 1.菜鸟设计模式 2.Head First Design Patterns(书.强烈推荐); 3.大话设计模 ...

最新文章

  1. CNCC 2019 | 计算领域年度盛会—中国计算机大会10月将在苏州举行
  2. 惠斯通电桥信号调理芯片_瑞萨推出集成LIN输出接口的传感器信号调理芯片,适用于电动/混动汽车HVAC系统...
  3. kafka如何彻底删除topic及数据
  4. Redis操作Set类型
  5. 所属的用户_关于chmod(变更用户对此文件的相关权限)超详细说明,小白秒懂
  6. ftp完成版本更新php,php – 将开发团队从FTP转换为版本控制系统
  7. 90后的你,有什么赚钱方式?
  8. Eclipse的安装
  9. Shopee跨境电商开店高频问题解答
  10. 机器人系统常用仿真软件工具介绍、效果与评价指标(2018年更新)
  11. Git学习使用方法总结(1)
  12. 带有鸿蒙logo的壁纸,鸿蒙OS Logo曝光
  13. 软件工程项目:电梯调度
  14. 运用三角不等式加速Kmeans聚类算法
  15. LaTex练习日记02 —— 字体设置
  16. cv2.imshow无法显示图像
  17. cm-14.1 Android系统启动过程分析(4)-init进程的启动、rc脚本解析、zygote启动、属性服务
  18. 【Nexus】Nexus简介与安装
  19. 交通运输——机器学习/深度学习资源列表
  20. lucene geohash 在外卖场景中,商家不规则多边形配送范围技术应用

热门文章

  1. Kaldi简介【开源语音识别工具】
  2. C++课程学习代码汇总基础
  3. cleanmymac苹果电脑必备mac系统垃圾清理工具分享
  4. 计算机程序中的自省程序(反射程序)(introspective program)是什么?(introspectable、introspection)
  5. Dubbo笔记 ㉗ : 服务自省-提供者
  6. 关于个人对培训的看法
  7. 文件——创建文件并写入内容
  8. 光线微弯传感器matlab仿真,基于输出光斑旋转的光纤微弯位移传感器
  9. 给自家人做个招聘广告,前后端和移动工程师看过来
  10. 六支团队共获第八届香港科大百万奖金创业大赛180万探索种子基金