浅谈常用的设计模式

参考文章:

单例模式 https://www.cnblogs.com/hellojava/p/3615502.html
观察者模式 https://www.cnblogs.com/luohanguo/p/7825656.html
装饰模式 https://blog.csdn.net/z4909801/article/details/59059263
六大原则:https://www.jianshu.com/p/bf92927c9d22

1.单例模式

(1):懒汉(线程不安全,在多线程中无法正常工作)

  private SingleTon(){}
    private static SingleTon instance;
    public static SingleTon getInstance(){
        if(instance==null){
            instance=new SingleTon();
        }
        return instance;
    }

(2):懒汉(线程··安全 synchronized同步方法)

public class SingleTon {
    private SingleTon(){}
    private static SingleTon instance;
    public static synchronized SingleTon getInstance(){
        if(instance==null){
            instance=new SingleTon();
        }
        return instance;
    }
}

(3):懒汉(线程··安全 synchronized同步代码块,双重校验锁)

public class SingleTon {
    private SingleTon(){}
    private static SingleTon instance;
    public static  SingleTon getInstance(){
        if(instance==null){
            synchronized (SingleTon.class){
                if(instance==null){
                    instance=new SingleTon();
                }
            }
        }
        return instance;
    }
}

(4).饿汉(一旦SingleTon 被装载了,instance会立马实例化)

public class SingleTon {
    private SingleTon(){}
    private static SingleTon instance=new SingleTon();
    public static  SingleTon getInstance(){
        return instance;
    }
}

(5).饿汉(静态内部类,这种方式的好处是即使SingleTon被装载了,instance也不会立马实例化)

public class SingleTon {
    private SingleTon(){}
    private static class SingleTonHolder {
        private static SingleTon instance=new SingleTon();
    }
    public static  SingleTon getInstance(){
        return SingleTonHolder.instance;
    }
}

(6)饿汉(静态代码块)

public class SingleTonSeven {
    private SingleTonSeven() {
    }
    private static SingleTonSeven singleTonSeven;
    static {
        singleTonSeven=new SingleTonSeven();
    }
    public   static SingleTonSeven getInstance(){
        return  singleTonSeven;
    }
}

(7)枚举

// 单例
public enum  SingleTonSix {
    Instance;
    SingleTonSix() {
        System.out.println("init");
    }
    public void print(){
        System.out.println("ffffffffffff");
    }
}

//测试
public static void main(String[] args) {

      // 系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统能。
        SingleTonSix singleTonSix1=SingleTonSix.Instance;
        singleTonSix1.print();
        SingleTonSix singleTonSix2=SingleTonSix.Instance;
        singleTonSix2.print();
        SingleTonSix singleTonSix3=SingleTonSix.Instance;
        singleTonSix3.print();
        SingleTonSix singleTonSix4=SingleTonSix.Instance;
        singleTonSix4.print();
    }

2.工厂模式

(1).普通工厂模式

public interface Sender {
    public void send();
}

public class MailSender implements Sender{
    @Override
    public void send() {
        System.out.println("this is mail sender");
    }
}

public class SmsSender implements  Sender {
    @Override
    public void send() {
        System.out.println("this is sms sender");
    }
}

public class SendFactoryOne {
    public Sender produce(String type){
        if(type.equals("mail")){
            return  new MailSender();
        }else if(type.equals("sms")){
            return  new SmsSender();
        }else{
            return null;
        }
    }
}

(2).工厂方法模式

public class SendFactoryTwo {
    public  Sender produceMail(){
       return new MailSender();
    }
    public  Sender produceSms(){
        return new SmsSender();
    }
}

(3).静态工厂方法模式

public class SendFactoryThree {
    public static Sender produceMail(){
       return new MailSender();
    }
    public static Sender produceSms(){
        return new SmsSender();
    }
}

(4).抽象工程模式

注意:工程方法模式有个问题,类的创建和扩展必须修改工厂类,这违背了闭包原则,所有用到抽象工厂模式,创建多个工厂类,这样一来,直接增加工厂类就可以了,不需要修改之前的代码。
public interface Provider {
    public Sender produce();
}

public class SendMailFactory implements Provider {
    @Override
    public Sender produce() {
        return new MailSender();
    }
}
public class SendSmsFactory implements Provider {
    @Override
    public Sender produce() {
        return new SmsSender();
    }
}
public class MainTest {
    public static void main(String[] args){
        SendFactoryOne sendFactoryOne=new SendFactoryOne();
        sendFactoryOne.produce("mail");
        sendFactoryOne.produce("sms");

         SendFactoryTwo sendFactoryTwo=new SendFactoryTwo();
         sendFactoryTwo.produceMail();
         sendFactoryTwo.produceSms();

         SendFactoryThree.produceMail();
         SendFactoryThree.produceSms();
         
         Provider provider=new SendMailFactory();
         Sender sender=provider.produce();
         sender.send();

         Provider provider1=new SendSmsFactory();
         Sender sender1=provider1.produce();
         sender1.send();
    }
}

3.观察者模式

类似于邮件订阅,当我们浏览一些博客或者wiki时,当你订阅了改文章,如果后续有更新,会及时通知你,是一种一对多的关系。(https://www.cnblogs.com/luohanguo/p/7825656.html)
(1) 、定义一个抽象观察者接口

public interface Observer {
    public void update();
}

(2)、定义一个抽象被观察者接口

public interface Observerable {
    public void registerObserver(Observer observer);
    public void removeObserver(Observer observer);
    public void notifyObservers();
}

(3).定义被观察者,实现了Observerable接口,对Observerable接口的三个方法进行了具体实现,同时有一个List集合,用以保存注册的观察者,等需要通知观察者时,遍历该集合即可,通知新增一个operation()用于通知所有的观察者。

public class WeChatServer implements Observerable {

   List  list=new ArrayList<>();//面向接口编程

    @Override
    public void registerObserver(Observer observer) {
        list.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        if(!list.isEmpty()){
            list.remove(observer);
        }
    }

    @Override
    public void notifyObservers() {
        for(int i=0;i

(4)、定义具体观察者,微信公众号的具体观察者为用户User1,User2

public class User1 implements Observer {
    @Override
    public void update() {
        System.out.println(User1.class.toString() +"has received the push message!");
    }
}
public class User2 implements Observer {
    @Override
    public void update() {
        System.out.println(User2.class.toString() +"has received the push message!");
    }
}

(5)、编写一个测试类

public class MainTest {
    public static void main(String[] args){
        WeChatServer server=new WeChatServer();
        User1 user1=new User1();
        User2 user2=new User2();
        server.registerObserver(user1);
        server.registerObserver(user2);
        server.operation();
    }
}
浅谈常用的设计模式_第1张图片
image.png

4.装饰模式

装饰模式就是给一个对象增加一些新的功能,而且是动态的,要求装饰对象和被装饰对象实现统一接口或者继承同一个父类,装饰对象持有被装饰对象的实例。
(1).Food类,让其他所有食物都来继承这个类

public class Food {
    private String food_name;
    public Food(){

    }
    public Food(String food_name) {
        this.food_name = food_name;
    }
    public String make(){
        return  food_name;
    }
}

(2).Bread类,Cream类,Vegetable类

public class Bread extends Food{
    private Food basic_food;
    public Bread(Food basic_food){
          this.basic_food=basic_food;
    }
    @Override
    public String make() {
        return basic_food.make()+"+面包";
    }
}

public class Cream extends Food {
    private  Food basic_food;

    public Cream(Food basic_food) {
        this.basic_food = basic_food;
    }

    @Override
    public String make() {
        return basic_food.make()+"+奶油";
    }
}

public class Vegetable extends Food {
    private Food basic_food;

    public Vegetable(Food basic_food) {
        this.basic_food = basic_food;
    }

    @Override
    public String make() {
        return basic_food.make()+"+蔬菜";
    }
}

(3).编写一个测试类

public class MainTest {

    public static void main(String[] args){
        Food food=new Food("香肠");
        Bread bread=new Bread(food);
        Cream cream=new Cream(bread);
        Vegetable vegetable=new Vegetable(cream);
        System.out.print("运行结果:"+vegetable.make()+"\n");
    }
}
image.png

5.适配器模式

(1).类适配器模式(通过继承来实现适配器功能)

我们以ps2与usb的转接为例:
Ps2接口:

public interface Ps2 {
    void isPs2();
}

Usb接口:

public interface Usb {
    void isUsb();
}

Usb接口实现类:Usber

public class Usber implements Usb {
    @Override
    public void isUsb() {

    }
}

适配器:AdapterOne

public class AdapterOne extends Usber implements Ps2{
    @Override
    public void isPs2() {
           isUsb();
    }
}

测试方法:

 public static void main(String[] args){
        //1.类适配,通过继承类适配
        Ps2 p=new AdapterOne();
        p.isPs2();
    }
(2).对象适配器模式(通过组合来实现适配器的功能)

适配器:AdapterTwo

public class AdapterTwo implements Ps2{
    private Usber usber;
    public AdapterTwo(Usber usber) {
        this.usber = usber;
    }
    @Override
    public void isPs2() {
        usber.isUsb();
    }
}

测试方法:

public class MainTest {
    public static void main(String[] args){
        //2.对象适配,通过组合实现
        Ps2 p=new AdapterTwo(new Usber());
        p.isPs2();
    }
}
注意:类适配和对象适配模式中所有的adapter均需要实现Ps2接口
(3).接口适配器模式(通过抽象类来实现)

目标接口A:

public interface A {
    void a();
    void b();
    void c();
    void d();
    void e();
}

A的实现类:Adapter

public abstract class Adapter implements A {
    @Override
    public void a() {

    }

    @Override
    public void b() {

    }

    @Override
    public void c() {

    }

    @Override
    public void d() {

    }

    @Override
    public void e() {

    }
}

继承自Adapter的MyAdapter:

public class MyAdapter extends Adapter {

    @Override
    public void a() {
        super.a();
        System.out.println("实现A方法");
    }

    @Override
    public void b() {
        super.b();
        System.out.println("实现B方法");
    }
}

测试方法:

  public static void main(String[] args){
        //3.接口适配,通过抽象类实现
        A aRealize=new MyAdapter();
        aRealize.a();
        aRealize.b();

    }

6.策略模式(一个人走楼梯上楼或者走电梯上楼)

这里以加减算法为例:
(1).定义抽象策略角色接口:Strategy

public interface Strategy {
     int calc(int num1,int num2);
}

(2).定义加法策略:AddStrategy

public class AddStrategy implements Strategy{
    @Override
    public int calc(int num1, int num2) {
        return num1+num2;
    }
}

(3).定义减法策略:SubStrategy

public class SubStrategy implements Strategy {
    @Override
    public int calc(int num1, int num2) {
        return num1-num2;
    }
}

(4).环境角色:Environment

public class Environment {
    private Strategy strategy;
    public Environment(Strategy strategy) {
        this.strategy = strategy;
    }

    public int calc(int a,int b){
        return strategy.calc(a,b);
    }
}

测试方法:

 public static void main(String[] args){
        Strategy addStrage=new AddStrategy();
        Environment environment=new Environment(addStrage);
        int sum1=environment.calc(10,10);
        System.out.println("Result1:"+sum1);
        Strategy subStrage=new SubStrategy();
        int sum2=subStrage.calc(20,10);
        System.out.println("Result2:"+sum2);
    }

7.Builder模式

public class Request {
    private String name;
    private String reason;
    private String days;
    private String groupLeaderInfo;
    private String managerInfo;
    private String departmentHeaderInfo;
    private String customInfo;
    public Request(Builder builder){
         // super();
          this.name=builder.name;
          this.reason=builder.reason;
          this.days=builder.days;
          this.groupLeaderInfo=builder.groupLeaderInfo;
          this.managerInfo=builder.managerInfo;
          this.departmentHeaderInfo=builder.departmentHeaderInfo;
          this.customInfo=builder.customInfo;

    }


    public static class Builder{
        private String name;
        private String reason;
        private String days;
        private String groupLeaderInfo;
        private String managerInfo;
        private String departmentHeaderInfo;
        private String customInfo;

        public Builder setName(String name) {
            this.name = name;
            return this;
        }

        public Builder setReason(String reason) {
            this.reason = reason;
            return this;
        }

        public Builder setDays(String days) {
            this.days = days;
            return this;
        }

        public Builder setGroupLeaderInfo(String groupLeaderInfo) {
            this.groupLeaderInfo = groupLeaderInfo;
            return this;
        }

        public Builder setManagerInfo(String managerInfo) {
            this.managerInfo = managerInfo;
            return this;
        }

        public Builder setDepartmentHeaderInfo(String departmentHeaderInfo) {
            this.departmentHeaderInfo = departmentHeaderInfo;
            return this;
        }

        public Builder setCustomInfo(String customInfo) {
            this.customInfo = customInfo;
            return this;
        }
        public Builder newRequest(Request request){
            this.name=request.name;
            this.days=request.days;
            this.reason=request.reason;
            if(request.getGroupLeaderInfo()!=null&&!request.getGroupLeaderInfo().equals("")){
                this.groupLeaderInfo=request.groupLeaderInfo;
            }
            if(request.getManagerInfo()!=null&&!request.getManagerInfo().equals("")){
                this.managerInfo=request.managerInfo;
            }
            if(request.getDepartmentHeaderInfo()!=null&&!request.getDepartmentHeaderInfo().equals("")){
                this.departmentHeaderInfo=request.getDepartmentHeaderInfo();
            }
            return this;
        }

        public Request build(){
            return new Request(this);
        }
    }

    public String getName() {
        return name;
    }

    public String getReason() {
        return reason;
    }

    public String getDays() {
        return days;
    }

    public String getGroupLeaderInfo() {
        return groupLeaderInfo;
    }

    public String getManagerInfo() {
        return managerInfo;
    }

    public String getDepartmentHeaderInfo() {
        return departmentHeaderInfo;
    }

    public String getCustomInfo() {
        return customInfo;
    }

    @Override
    public String toString() {
        return "Request{" +
                "name='" + name + '\'' +
                ", reason='" + reason + '\'' +
                ", days='" + days + '\'' +
                ", groupLeaderInfo='" + groupLeaderInfo + '\'' +
                ", managerInfo='" + managerInfo + '\'' +
                ", departmentHeaderInfo='" + departmentHeaderInfo + '\'' +
                ", customInfo='" + customInfo + '\'' +
                '}';
    }
}

测试方法:

  public static void main(String[] args){
       Request request=new Request.Builder()
               .setName("shuijian")
               .setReason("GoHome")
               .setDays("2days")
               .build();
       System.out.println(request.toString());
    }

8.责任链模式

实例场景
在公司内部员工请假一般情况是这样的:员工在OA系统中提交一封请假邮件,该邮件会自动转发到你的直接上级领导邮箱里,如果你的请假的情况特殊的话,该邮件也会转发到你上级的上级的邮箱,根据请假的情况天数多少,系统会自动转发相应的责任人的邮箱。我们就以这样一种场景为例完成一个责任链模式的代码。为了更清晰的描述这种场景我们规定如下:
① GroupLeader(组长 ):他能批准的假期为2天,如果请假天数超过2天就将请假邮件自动转发到组长和经理邮箱。
② Manager(经理):他能批准的假期为4天以内,如果请假天数大于4天将该邮件转发到自动转发到组长、经理和部门领导的邮箱。
③ DepartmentHeader(部门领导):他能批准的假期为7天以内,如果大于7天就只批准7天。

(1).构造Request对象,如:Builder模式中的Request
(2).构造批准结果对象Result
public class Result {
    public boolean isRality;
    public String  info;

    public Result(boolean isRality, String info) {
        this.isRality = isRality;
        this.info = info;
    }

    public boolean isRality() {
        return isRality;
    }

    public void setRality(boolean rality) {
        isRality = rality;
    }

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }

    @Override
    public String toString() {
        return "Result{" +
                "isRality=" + isRality +
                ", info='" + info + '\'' +
                '}';
    }
}
(3).定义一个接口,这个接口用于处理Request和获取请求结果Result
public interface Ratify {
    //处理请求
    public Result deal(Chain chain);
    //对request和result封装,用来转发
    interface Chain{
        //获取当前的request
        Request request();
        //转发Request
        Result proceed(Request request);
    }
}

看到上面的接口,可能会有人迷惑:在接口Ratify中为什么又定义一个Chain接口呢?其实这个接口是单独定义还是内部接口没有太大关系,但是考虑到Chain接口与Ratify接口的关系为提高内聚性就定义为内部接口了。定义Ratify接口是为了处理Request那为什么还要定义Chain接口呢?这正是责任链接口的精髓之处:转发功能及可动态扩展“责任人”,这个接口中定义了两个方法一个是request()就是为了获取request,如果当前Ratify的实现类获取到request之后发现自己不能处理或者说自己只能处理部分请求,那么他将自己的那部分能处理的就处理掉,然后重新构建一个或者直接转发Request给下一个责任人。可能这点说的不容易理解,我举个例子,在Android与后台交互中如果使用了Http协议,当然我们可能使用各种Http框架如HttpClient、OKHttp等,我们只需要发送要请求的参数就直接等待结果了,这个过程中你可能并没有构建请求头,那么框架帮你把这部分工作给做了,它做的工程中如果使用了责任链模式的话,它肯定会将Request进行包装(也就是添加请求头)成新的Request,我们姑且加他为Request1,如果你又希望Http做本地缓存,那么Request1又会被转发到并且重新进一步包装为Request2。总之Chain这个接口就是起到对Request进行重新包装的并将包装后的Request进行下一步转发的作用。如果还不是很明白也没关系,本实例会演示这一功能机制。

(4).实现Chain接口的的真正的包装Request和转发功能
public class RealChain implements Ratify.Chain {
    public Request request;
    public List ratifyList;
    public int index;
    /**
     * 构造方法
     *
     * @param ratifyList
     *            Ratify接口的实现类集合
     * @param request
     *            具体的请求Request实例
     * @param index
     *            已经处理过该request的责任人数量
     */
    public RealChain(List ratifyList, Request request,int index) {
        this.request = request;
        this.ratifyList = ratifyList;
        this.index = index;
    }
    /**
     * 方法描述:具体转发功能
     */
    @Override
    public Result proceed(Request request) {
        Result proceed=null;
        if(ratifyList.size()>index){
          RealChain realChain=new RealChain(ratifyList,request,index+1);
          Ratify ratify=ratifyList.get(index);
          proceed=ratify.deal(realChain);
        }
        return proceed;
    }

    /***
     * 方法描述:返回当前Request对象或者返回当前进行包装后的Request对象
     * @return
     */
    @Override
    public Request request() {
        return request;
    }
}
(5).GroupLeader、Manager和DepartmentHeader,并让他们实现Ratify接口
public class GroupLeader implements Ratify {
    @Override
    public Result deal(Chain chain) {
        Request request=chain.request();
        System.out.println("GroupLeader====>request:"+request.toString());
        if(Integer.parseInt(request.getDays())>1){
            //包装新的Request对象
            Request newRequest=new Request.Builder().newRequest(request).setGroupLeaderInfo(request.getName()+"平时表现不错,而且现在项目不忙").build();
            return chain.proceed(newRequest);
        }
        return new Result(true,"GroupLeader:早去早回");
    }
}
public class Manager implements Ratify {
    @Override
    public Result deal(Chain chain) {
        Request request=chain.request();
        System.out.println("Manager====>request:"+request.toString());
        if(Integer.parseInt(request.getDays())>3){
            //构建新的Request
            Request newRequest=new Request.Builder().newRequest(request).setManagerInfo(request.getName()+"每月的KPI考核还不错,可以批准").build();
            return chain.proceed(newRequest);

        }
        return new Result(true,"Manager:早点把事情办完,项目离不开你");
    }
}
public class DepartmentHeader implements Ratify {
    @Override
    public Result deal(Chain chain) {
        Request request=chain.request();
        System.out.println("DepartmentHeader=====>request:"+request.toString());
        if(Integer.parseInt(request.getDays())>7){
              return  new Result(false,"DepartmentHeader:你这个时间太长,不能批准");
        }
        return new Result(true,"DepartmentHeader:不要着急,把事情处理完在回来!");
    }
}
public class CustomInterceptor implements Ratify {
    @Override
    public Result deal(Chain chain) {
        Request request=chain.request();
        System.out.println("CustomInterceptor====>"+request.toString());
        String reason=request.getReason();
        if(reason!=null&&reason.equals("事假")){
              Request newRequest=new Request.Builder().newRequest(request).setCustomInfo(request.getName()+"请的是事假,而且很着急,请领导重视一下").build();
              System.out.println("CustomInterceptor====>转发请求");
              return chain.proceed(newRequest);
        }
        return new Result(true,"同意请假");
    }
}
(6).责任链模式工具类
public class ChainOfResponsibilityClient {
    private ArrayList ratifies;

    public ChainOfResponsibilityClient() {
        ratifies=new ArrayList<>();
    }

    /**
     * 为了展示“责任链模式”的真正的迷人之处(可扩展性),在这里构造该方法以便添加自定义的“责任人”
     * @param ratify
     */
    public void addRatifys(Ratify ratify){
        ratifies.add(ratify);
    }

    /***
     *
     * 方法描述:执行请求
     * @param request
     * @return
     */

    public Result execute(Request request){
        ArrayList arrayList=new ArrayList<>();
        arrayList.addAll(ratifies);
        arrayList.add(new GroupLeader());
        arrayList.add(new Manager());
        arrayList.add(new DepartmentHeader());
        RealChain realChain=new RealChain(arrayList,request,0);
        return realChain.proceed(request);
    }
}
(6).测试方法
 public static void main(String[] args){
        //写法一
        Request.Builder builder=new Request.Builder();//通过静态内部类构建builder对象
        builder.setName("zhangsan");
        builder.setDays("5");
        builder.setReason("事假");
        Request request=builder.build();//build方法返回request对象
        //写法二
        Request request1=new Request.Builder().setName("lisi").setDays("7").setReason("事假").build();
        //System.out.print("结果:"+request.toString());

        ChainOfResponsibilityClient client=new ChainOfResponsibilityClient();
        //添加自定义的拦截器到责任人列表顶端
        client.addRatifys(new CustomInterceptor());
        Result result=client.execute(request);
        System.out.println("结果:"+result.toString());

    }

9.享元模式

(1).定义一个接口作为享元角色

public interface IBike {
    void ride(int hours);
}

(2).实现IBike接口,作为具体的享元角色

public class ShareBike implements IBike{
    private int price=2 ;

    @Override
    public void ride(int hours) {
        int total=2*hours;
        System.out.println("ride bike total spend "+total+" RMB");

    }
}

(3).创建享元工厂

public class ShareBikeFactory {
    Map pool=new HashMap<>();
    public  IBike getBike(String name){
        IBike iBike=null;
        if(!pool.containsKey(name)){
            iBike=new ShareBike();
            pool.put(name,iBike);
            System.out.println("交了199元押金,可以用车:"+name);
        }else{
            iBike=pool.get(name);
            System.out.println("押金已交,直接用车:"+name);
        }
        return iBike;
    }
}

(4).测试类

 public static void main(String[] args) {
        ShareBikeFactory shareBikeFactory=new ShareBikeFactory();
        //第一次骑ofo,交押金
        IBike ofo1=shareBikeFactory.getBike("ofo");
        ofo1.ride(2);
        //第一次骑mobike,交押金
        IBike mobike=shareBikeFactory.getBike("mobike");
        mobike.ride(3);
        //第二次骑mobike,不交押金
        IBike ofo2=shareBikeFactory.getBike("ofo");
        ofo2.ride(4);
    }

10.模板方法模式

(1).创建抽象类,定义算法框架

public abstract class Postman {

    public final void post(){//这里声明为final,不希望子类覆盖这个方法,防止更改流程
        prepare();
        call();
        if(isSign()){
            sign();
        }else{
            refuse();
        }
    }

    protected void refuse() {
    }

    protected void sign() {
        System.out.println("派送完毕,客户已经签收!");
    }

    protected boolean isSign() {
        return true;
    }

    protected abstract void call();

    protected void prepare() {
        System.out.println("快递已经到达,准备派送...");
    }
}

需要注意的是上面的抽象类(Postman)包含了三种类型的方法:抽象方法、具体方法和钩子方法。
抽象方法:需要子类去实现。如上面的call()。
具体方法:抽象父类中直接实现。如上面的prepare()和sign()。
钩子方法:有两种,第一种,它是一个空实现的方法,子类可以视情况来决定是否要覆盖它,如上面的refuse();第二种,它的返回类型通常是boolean类型的,一般用于对某个条件进行判断,如果条件满足则执行某一步骤,否则将不执行,如上面的isSign()。
(2).创建具体实现类,定义算法框架
PostmanA:

public  class PostmanA extends Postman{
    @Override
    protected void call() {
        System.out.println("联系收货人A,准备派送...");
    }
}

PostmanB:

public  class PostmanB extends Postman{
    @Override
    protected void call() {
        System.out.println("联系收货人B,准备派送...");
    }

    @Override
    protected boolean isSign() {
        return false;
    }

    @Override
    protected void refuse() {
        super.refuse();
        System.out.println("商品与实物不符,拒绝签收!");
    }
}

(3).测试类

 public static void main(String[] args){
        //A收货人正常签收
        Postman postmanA=new PostmanA();
        postmanA.post();
        //B收货人拒绝签收
        Postman postmanB=new PostmanB();
        postmanB.post();
    }
浅谈常用的设计模式_第2张图片
image.png

11.备忘录模式

以游戏存档为例:
(1).创建发起人角色:Game

public class Game {
    private int mLevel=0;
    private int mIcon=0;

    /***
     * 开始游戏
     */
    public void paly(){
        System.out.print("升级了");
        mLevel++;
        System.out.println("当前等级为:"+mLevel);
        mIcon+=32;
        System.out.println("获得金币:"+mIcon);
        System.out.println("当前金币数量为:"+mIcon);
    }

    /***
     * 退出游戏
     */
    public void exit(){
        System.out.println("退出游戏,属性为:等级="+mLevel+",金币="+mIcon);
    }

    //创建备忘录
    public Memo createMemo(){
        Memo memo=new Memo();
        memo.setmLevel(mLevel);
        memo.setmIcon(mIcon);
        return memo;
    }

    public void setMemo(Memo memo){
        mLevel=memo.getmLevel();
        mIcon=memo.getmIcon();
    }

}

(2).创建备忘录角色:Memo

public class Memo {
    private int mLevel;//等级
    private int mIcon;//金币数量

    public int getmLevel() {
        return mLevel;
    }

    public void setmLevel(int mLevel) {
        this.mLevel = mLevel;
    }

    public int getmIcon() {
        return mIcon;
    }

    public void setmIcon(int mIcon) {
        this.mIcon = mIcon;
    }
}

(3).创建负责人角色:CreateMemo

public class CreateMemo {
    private Memo memo;

    public Memo getMemo() {
        return memo;
    }

    public void setMemo(Memo memo) {
        this.memo = memo;
    }
}

(4).测试类

public static void main(String[] args){
        Game game=new Game();
        game.paly();
        CreateMemo createMemo=new CreateMemo();
        createMemo.setMemo(game.createMemo());//游戏存档
        game.exit();
        //第二次进入游戏
        System.out.println("第二次进入游戏");
        Game secondGame=new Game();
        secondGame.setMemo(createMemo.getMemo());//取出之前备忘录中的数据
        secondGame.paly();
        secondGame.exit();
    }

12.原型模式

(1).创建具体原型类
实现Cloneable接口:

public class Card implements Cloneable {
    private int num;//卡号
    private Spec spec=new Spec();
    public Card(){
        System.out.println("Card 执行构造函数");
    }

    @Override
    protected Card clone() throws CloneNotSupportedException {
        System.out.println("clone时不执行构造函数");
        Card card= (Card) super.clone();
        card.spec=spec.clone();//对Spce对象也调用clone,实现深拷贝
        return card;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public Spec getSpec() {
        return spec;
    }

    public void setSpec(int width,int  length) {
        spec.width=width;
        spec.length=length;
    }

    public class Spec implements Cloneable{
        private int width;
        private int length;

        public int getWidth() {
            return width;
        }

        public void setWidth(int width) {
            this.width = width;
        }

        public int getLength() {
            return length;
        }

        public void setLength(int length) {
            this.length = length;
        }

        @Override
        protected Spec clone() throws CloneNotSupportedException {
            return (Spec) super.clone();
        }
    }

    @Override
    public String toString() {
        return "Card{" +
                "num=" + num +
                ", spec=" +"{width="+spec.getWidth()+",length="+spec.getLength()+
                '}';
    }
}

(2).测试类

 public static void main(String[] args) throws CloneNotSupportedException {
        Card card1=new Card();
        card1.setNum(111);
        card1.setSpec(66,67);
        System.out.println(card1.toString());
        System.out.println("---------------------");
        //拷贝
        Card card2=card1.clone();
        System.out.println(card2.toString());
        System.out.println("---------------------");
        //拷贝之后,card2对num进行重新赋值
        card2.setNum(222);
        System.out.println(card1.toString());
        System.out.println(card2.toString());
        System.out.println("---------------------");
        //拷贝之后,card2对Spec进行重新赋值之后,连card1也跟着改变了,这种就是浅拷贝
        card2.setSpec(76,77);
        System.out.println(card1.toString());
        System.out.println(card2.toString());
        System.out.println("---------------------");
    }
浅谈常用的设计模式_第3张图片
image.png

13.命令模式

(1).创建命令接口Command

public interface Command {
    void execute();
}

(2).创建命令接口实现类:ShutDownCommand

public class ShutDownCommand implements Command {
    Receiver receiver;

    public ShutDownCommand(Receiver receiver) {
        this.receiver = receiver;
    }

    @Override
    public void execute() {
        System.out.println("命令角色执行关机命令");
        receiver.action();
    }
}

(3).创建命令执行者Receiver

public class Receiver {
    public void action(){
        System.out.println("接收者执行具体的操作");
        System.out.println("开始执行关机命令");
        System.out.println("退出所有程序");
        System.out.println("关机...");
    }
}

(4).创建调用者Invoker

public class Invoker {
    private  Command command;
    public Invoker(Command command) {
        this.command = command;
    }
    public void action(){
        System.out.println("调用者执行命令");
        command.execute();
    }
}

测试方法:

public static void main(String[] args){
       Receiver receiver=new Receiver();//创建命令接收者
       Command command=new ShutDownCommand(receiver);//创建一个命令的具体实现对象,并指定命令接收者
       Invoker invoke=new Invoker(command);//创建一个命令调用者,并指定具体命令
       invoke.action();
    }
注意:此处调用者与接受者之间的解藕。易于扩展,扩展命令只需新增具体命令类即可,符合开放封闭原则。
浅谈常用的设计模式_第4张图片
image.png

14.代理模式

(1).静态代理
IBuy接口

public interface IBuy {
    void buy();
}

IBuy接口实现类:Demestic,OverSea

public class Demestic implements IBuy {
    @Override
    public void buy() {
        System.out.println("国内要买一个包");
    }
}
public class Oversea implements IBuy {
    IBuy buyer;
    public Oversea(IBuy buyer) {
        this.buyer=buyer;
    }

    @Override
    public void buy() {
        System.out.println("我是海外代购");
        buyer.buy();
    }
}

测试方法:

  public static void main(String[] args){
        //静态代理
        IBuy demestic=new Demestic();
        IBuy oversea=new Oversea(demestic);
        oversea.buy();
        System.out.println("----------------------------------------");
        
    }

(2).动态代理(代理类在程序运行时动态生成)
动态代理类:DynamicProxy

public class DynamicProxy implements InvocationHandler {
    private Object obj;//被代理的对象
    public DynamicProxy(Object obj) {
        this.obj=obj;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("海外动态代理调用方法:"+method.getName());
        Object result=method.invoke(obj,args);
        return result;
    }
}

测试方法:

  public static void main(String[] args){
        //动态代理
        IBuy demestics=new Demestic();//被代理类
        ClassLoader classLoader=demestics.getClass().getClassLoader();//获取classloader
        Class[] classes=new Class[]{IBuy.class};//接口类的class数组
        DynamicProxy dynamicProxy=new DynamicProxy(demestics);//创建动态代理
        IBuy oversea1= (IBuy) Proxy.newProxyInstance(classLoader,classes,dynamicProxy);
        oversea1.buy();//调用海外代购的buy,此处实际上是调用dynamicProxy.invoke()方法
        System.out.println("----------------------------------------");

    }
image.png

你可能感兴趣的:(浅谈常用的设计模式)