设计模式读书笔记汇总

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

    属于工厂模式,是一种弱化的工厂模式
    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
         */
        @Override
        public 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
    */
   @Override
   public 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 = "鸡腿堡";
    }

    @Override
    public 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;
    }

    @Override
    public String getName() {
        return humburger.getName()+" 加生菜";
    }

    @Override
    public 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());
    }

    @Override
    public String getName() {
        return humburger.getName() + " 加辣椒";
    }

    @Override
    public 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 {

    @Override
    public void submit() {
        System.out.println("老板拖欠工资!因此申请仲裁!");
    }

    @Override
    public void burden() {
        System.out.println("这是合同书和过去一年银行的流水账单!");
    }

    @Override
    public void defend() {
        System.out.println("证据确凿,不用再多说了!");
    }

    @Override
    public void finish() {
        System.out.println("诉讼成功!马上发工资");
    }
}
  • 代理律师
public class Lawyer implements ILawsuit {
    private ILawsuit iLawsuit;

    public Lawyer(ILawsuit iLawsuit) {
        this.iLawsuit = iLawsuit;
    }

    @Override
    public void submit() {
        iLawsuit.submit();
    }

    @Override
    public void burden() {
        iLawsuit.burden();
    }

    @Override
    public void defend() {
        iLawsuit.defend();
    }

    @Override
    public 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 {
    @Override
    public void method() {
        System.out.println("我是具体的产品A");
    }
}

public class ConcreteProductB extends Product {
    @Override
    public 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 {
    @Override
    public <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 {
    @Override
    protected void login() {
//        注意:此处省略了super
//        super.login();
        System.out.print("程序员的电脑只需要用户和密码的验证就行");
    }
}
  • 具体流程改变(军事使用电脑类)
public class MilitaryComputer extends AbstractComputer {
    @Override
    protected void checkHardware() {
        super.checkHardware();
        System.out.println("检查硬件防火墙");
    }

    @Override
    protected 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();

    @Override
    public String toString() {
        return "Computer{" +
                "mBoard='" + mBoard + '\'' +
                ", mDisplay='" + mDisplay + '\'' +
                ", mOs='" + mOs + '\'' +
                '}';
    }
}

//具体的Computer类
public class Macbook extends Computer {
    public Macbook() {
    }

    @Override
    public 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();
    //创建Computer
    public abstract Computer create();
}

//具体的builder类
public class MacbookBuilder extends Builder {
    private Computer computer = new Macbook();

    @Override
    public void buildBoard(String board) {
        computer.setmBoard(board);
    }

    @Override
    public void buildDisplay(String display) {
        computer.setmDisplay(display);
    }

    @Override
    public void buildOS() {
        computer.setmOs();
    }

    @Override
    public 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 {
    @Override
    public void tire() {
        System.out.println("普通轮胎");
    }
}

public class SuvTire implements ITire {
    @Override
    public void tire() {
        System.out.println("SUV轮胎");
    }
}


public class DomesticEngine implements IEngine {
    @Override
    public void engine() {
        System.out.print("国产发动机");
    }
}

public class ImportEngine implements IEngine {
    @Override
    public void engine() {
        System.out.print("进口发动机");
    }
}

public class NormalBrake implements IBreak {
    @Override
    public void bradk() {
        System.out.print("普通制动");
    }
}

public class SeniorBrake implements IBreak {
    @Override
    public void bradk() {
        System.out.print("高级制动");
    }
}
  1. 具体实现

public class Q3Factory extends CarFactory {
    @Override
    public ITire createTire() {
        return new NormalTire();
    }

    @Override
    public IEngine vreateEngine() {
        return new DomesticEngine();
    }

    @Override
    public IBreak iBreak() {
        return new NormalBrake();
    }
}


public class Q7Factory extends CarFactory {
    @Override
    public ITire createTire() {
        return new SuvTire();
    }

    @Override
    public IEngine vreateEngine() {
        return new ImportEngine();
    }

    @Override
    public 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 {
    @Override
    public void nextChannel() {
        System.out.println("下一频道");
    }

    @Override
    public void prevChannel() {
        System.out.println("上一频道");
    }

    @Override
    public void tureUp() {
        System.out.println("调高音量");
    }

    @Override
    public void turnDown() {
        System.out.println("调低音量");
    }
}
//关机后的操作
public class PowerOffState implements TvState {
    @Override
    public void nextChannel() {

    }

    @Override
    public void prevChannel() {

    }

    @Override
    public void tureUp() {

    }

    @Override
    public void turnDown() {

    }
}
//设置两种状态
public interface PowerController {
    void powerOn();
    void powerOff();
}
//遥控器
public class TvController implements PowerController {
    TvState mTvState;

    public void setmTvState(TvState mTvState) {
        this.mTvState = mTvState;
    }

    @Override
    public void powerOn() {
        setmTvState(new PowerOnState());
    }

    @Override
    public 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;
    }

    @Override
    public void update(Observable observable, Object data) {
        System.out.println("Hi,  " + name + "新内容来啦");
    }

    @Override
    public 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);
    }

    @Override
    public void attack() {
        System.out.println("前锋  进攻---->>>" + name);
    }

    @Override
    public void defense() {
        System.out.println("前锋  防守---->>>" + name);
    }
}

//后卫
public class Center extends Player {
    public Center(String name) {
        super(name);
    }

    @Override
    public void attack() {
        System.out.println("后卫  进攻---->>>" + name);
    }

    @Override
    public 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);
    }

    @Override
    public void attack() {
        wjzf.进攻();
    }

    @Override
    public 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;

    @Override
    public 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 方法
    @Override
    public 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);
    }

    @Override
    public void add(Company c) {
        children.add(c);
    }

    @Override
    public void remove(Company c) {
        children.remove(c);
    }
}

//财务类
public class FinanceDepartment extends Company {
    public FinanceDepartment(String name) {
        super(name);
    }

    @Override
    public void add(Company c) {

    }

    @Override
    public void remove(Company c) {

    }
}

//人事部
public class HRDepartment extends Company {
    public HRDepartment(String name) {
        super(name);
    }

    @Override
    public void add(Company c) {

    }

    @Override
    public 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;
    }

    @Override
    public 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;
    }

    @Override
    public boolean hasNext() {
        return !(position > list.size() - 1 || list.get(position) == null);
    }

    @Override
    public 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;
    }

    @Override
    public boolean hasNext() {
        return !(position > array.length - 1 || array[position] == null);
    }

    @Override
    public 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, "男", "程序员");
    }

    @Override
    public 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;
    }

    @Override
    public 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 {
    @Override
    public String addSomething() {
        return "原味";
    }
}

public class Sugar extends CoffeeAdditivies {
    @Override
    public 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);
    }

    @Override
    public void makeCoffee() {
        System.out.println("大杯的" + impl + "咖啡");
    }
}

public class SmallCoffee extends Coffee {
    public SmallCoffee(CoffeeAdditivies impl) {
        super(impl);
    }

    @Override
    public 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;
    }

    @Override
    public void execute() {
        tetrisMachine.toLeft();
    }
}

public class RightCommand implements Command {
    private TetrisMachine tetrisMachine;

    public RightCommand(TetrisMachine tetrisMachine) {
        this.tetrisMachine = tetrisMachine;
    }

    @Override
    public 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 {

    @Override
    public int limit() {
        return 1000;
    }

    @Override
    public void handle(int money) {
        System.out.println("组长批复报销" + money + "元");
    }
}

public class Director extends Leader {
    @Override
    public int limit() {
        return 5000;
    }

    @Override
    public void handle(int money) {
        System.out.println("主管批复报销" + money + "元");
    }
}

public class Boss extends Leader {
    @Override
    public int limit() {
        return Integer.MAX_VALUE;
    }

    @Override
    public 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;
  }

  @Override
  public 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;
    }

    @Override
    public 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;
    }


    @Override
    public int interpret() {
        return 0;
    }
}

public class AdditionExpression extends OperatorExpression {

    public AdditionExpression(ArithmeticExpression expression1, ArithmeticExpression expression2) {
        super(expression1, expression2);
    }

    @Override
    public 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 {
    @Override
    public void visit(Engineer engineer) {
        System.out.println("工程师 : " + engineer.name + ",KPI : " + engineer.kpi);
    }

    @Override
    public void visit(Manager leader) {
        System.out.println("工程师 : " + leader.name + ",KPI : " + leader.kpi + ",新产品数量 : " + leader.getProducts());
    }
}

public class CTOVisitor implements Visitor {
    @Override
    public void visit(Engineer engineer) {
        System.out.println("工程师 : " + engineer.name + "代码函数 : " + engineer.getCodeLines());
    }

    @Override
    public 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);
    }

    @Override
    public 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);
    }

    @Override
    public 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看的报表 ===========");
        //设置访问者,这里是CEO
        report.showReport(new CEOVisitor());

        System.out.println("=========== 给CTO看的报表 ===========");
        //注入另一个访问者,CTO
        report.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 );
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值