可不可以用工厂模式创建太阳系的模型,包括太阳、地球、月亮和星星?

解决方案 »

  1.   

    可以。
    做一个抽象父类:星球
    做一个工厂,提供某星球对象,可能是太阳、地球等...不过既然是构建一个复杂结构体(太阳系),builder模式可能更合适。
      

  2.   

    大侠们觉得builder模式更合适?现在模式选择迷惑中,求解释
      

  3.   

    嗯,我得好好考虑一下是工厂合适,还是builder合适,还有就是太阳、地球和月球这三个线程怎么实现合理的同步,sleep()可不可以?
      

  4.   

    谢谢各位大侠了,现在把部分代码贴上来,请各位大侠指导指导,自转只实现了太阳的,用的是策略模式,但大体的意思都差不多,用模式也是迫不得已,要为以后扩展星星作准备。interface Planet {
    public void run();
    public void start();
    }
     
     
    class sun extends Thread implements Planet                 //太阳类,描述太阳线程
    {
      JPanel  s_panel;
      int     s_size;         //太阳大小
      Color   s_color;        //太阳颜色
      int s_x=200,  s_y=180;//太阳所在位置坐标
      
      
      public sun(JPanel j,int s,Color c)
      {
      s_panel=j;
      s_size=s;
      s_color=c;

      }
      
      public void run()
      {
      Graphics g=s_panel.getGraphics();
      int sp_x=220,sp_y=200;
      double c=0,xp,yp;
         while(true)
        {
      //设置太阳颜色,画出太阳
      g.setColor(s_color);
      g.fillOval(s_x,s_y,s_size,s_size);
      c+=0.05;
      xp=13*Math.cos(c);    
      yp=13*Math.sin(c);
      
      sp_x=(int)xp+220;
      sp_y=(int)yp+200;
      g.setColor(Color.black);
      g.fillOval(sp_x,sp_y,8,8);
      try{
      Thread.sleep(100);
      }catch(Exception e)
      {
      System.out.println("execption sleep");
      }
      }
      }
    }
    class earth extends Thread  implements Planet                  //地球类,描述地球线程
    {
      JPanel e_panel;
      int    e_size;             //地球大小
      Color  e_color;            //地球颜色
      int e_x,e_y;
      
      public earth(JPanel j,int e,Color c)
      {
         e_panel=j;
         e_size=e;
         e_color=c;
      }
      public void run()
      {
      Graphics g=e_panel.getGraphics();     //得到画板句柄
      int e_x=300,  e_y=280;             //地球的起始坐标
      double a=0,xx,yy;
      while(true)
      {
      //清除上次所画的图
      g.setColor(Color.WHITE);
      g.fillOval(e_x,e_y,e_size,e_size);
      
      g.setColor(e_color);
      a+=0.05;                //地球每次转过的弧度
      //计算弧度变化后相应的坐标变化
      xx=150*Math.cos(a);    
      yy=100*Math.sin(a);
      //加上太阳的起始位置坐标(即平移)
      e_x=(int)xx+200;
      e_y=(int)yy+180;
      g.fillOval(e_x,e_y,e_size,e_size);
      try{
      Thread.sleep(100);
      }catch(Exception e)
      {
      System.out.println("execption sleep");
      }
      
      
      }
      }
    }
    class moon extends Thread implements Planet
    {
    JPanel m_panel;
    int m_size;
    Color m_color;
    int m_x=0,m_y=0;

    public moon(JPanel j,int s,Color c)
    {
    m_panel=j;
    m_size=s;
    m_color=c;
    }
    public void run()
    {
    Graphics g=m_panel.getGraphics();
    double a=0,b=0,xx,yy,exx,eyy;
    while(true)
    {
      g.setColor(Color.WHITE);
      g.fillOval(m_x,m_y,m_size,m_size);
      
      g.setColor(m_color);
      a+=0.05;  b+=0.6;
      xx=150*Math.cos(a);
      yy=100*Math.sin(a);
      exx=35*Math.cos(b)+(int)xx+200;
      eyy=35*Math.sin(b)+(int)yy+180;
      m_x=(int)exx;
      m_y=(int)eyy;
      g.fillOval(m_x,m_y,m_size,m_size);
      try{
      Thread.sleep(100);
      }catch(Exception e)
      {
      System.out.println("execption sleep");
      }
    }
    }
    }
    class CreatePlanet
    {
    private Planet planet;
    public CreatePlanet(Planet planet)
    {
    this.planet=planet;
    }
    public void roll()
    {
    this.planet.start();
    }}class Frame extends JFrame
    {
     JPanel s_panel;
     
    public Frame()
    {
    super("Sun-Earth-Moon System!");
    //创建面板
    s_panel=new JPanel();
    s_panel.setBounds(0,0,500,400);
    s_panel.setBackground(Color.WHITE);
    //创建容器
    Container c=this.getContentPane();
    c.setLayout(null);
    c.add(s_panel);

    this.setBounds(100,50,500,500); 
    this.setResizable(false); 
    this.setVisible(true);
    this.setDefaultCloseOperation(EXIT_ON_CLOSE);

    CreatePlanet planet;
    planet=new CreatePlanet(new sun(s_panel,50,Color.RED));
    planet.roll();
    planet=new CreatePlanet(new earth(s_panel,25,Color.BLUE));
    planet.roll();
    planet=new CreatePlanet(new moon(s_panel,15,Color.gray));
    planet.roll();
    }
    }
    public class God 
    {
    public static void main(String[] args)
    {
    new Frame();

    }
    }
      

  5.   

    其实不一定非的往设计模式中套,《深入浅出设计模式》中有说如果增加了模式之后问题反而复杂了,就抛弃到模式,可以先见一个星球的interface,包括星球的操作,然后分别建恒星,行星,彗星等等的抽象类,这些抽象类可以引用星球的interface,建立太阳系模型时按照星球类型不同,继承不同抽象类,然后实现就行了
      

  6.   

    这个问题 用的着用模式吗`?
    (扩展的最基本原则 是 不更改现有代码 只要接口(抽象类 接口 上层类)设置合理 一般都能满足要求的)
    一定要模式的话 模板 策略 倒是值得考虑 (你的代码我没看 纯属经验之谈)-->关于线程 可以无视\(^o^)/~
    线程这东西 不是你这么用的 你的cpu 可没有那么多核心 不可能同时执行!! 有可能 第一秒 1线程抢占cpu 算 太阳 第二秒才算月亮  既然都已经同步了 和单一线程有什么区别? 
    或者是 每个星球有自己的特定 运算 Ex 导入贴图 进行复杂运算 绘制这类 慢操作的话 倒是可以用命令模式来完成 (不对 勿喷)
      

  7.   

    不要给每一个星球分一个线程画图,你这样有可能月亮转了半天,地球却没有动弹...
    画图的线程只用一个就够了,依次画出太阳,月亮等即可
    同时使用计时器,比如设定为0.05秒旋转且绘制一次
    并要根据实际消耗的时间,计算旋转的角度,这样做出来的动画才是平滑的
    在行星接口中增加draw(Graphics g)绘制
    selfRoll()自转
    publicRoll()公转
    run(),start()不需要的楼主先尝试一下,如果实现不了我下午上代码
      

  8.   

    我理解这跟什么模式没关系。用也可以不用也行--signature------------------
    http://www.mowker.com/qklb/
      

  9.   

    倒是可以用命令模式来完成   命令模式不懂的话 可以参照 awt 时间分发线程EDT`
    就是 把所有线程 加入栈(一种另类的ArrayList)  利用 Thread.state(一个独立的调用别人线程的线程) 依次启动栈底线程(此步骤要同步)执行完毕 在加入栈(这一线程加入的目的 是为了统一绘制 或者统一输出的结果)  这是多么 复杂的步骤呀  !!  而且计算量 不大 而且 我想也用不到 涉及慢操作的步骤 所以 果断 单线程吧 
    (不对 勿喷``)囧
      

  10.   

    好了,上代码
    import java.awt.Graphics;
    import java.awt.Point;
    public interface Star
    {
    public void draw(Graphics g);
    public void selfRoll(long timeElapse);
    public void publicRoll(long timeElapse);
    public Point getCurPosition();
    }
    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Point;public class Planet implements Star
    {
    private Point curPosition;
    private int selfRollVelocity;
    private int publicRollVelocity;
    private Star publicRollTrack;
    private int publicRollTrackRadius;
    private int radius;
    private Point dir;
    private Color color;
    private String name;
    private double publicRollTrackAngle;
    private double selfRollTrackAngle;

    public Planet(String name,int r,int sv,int pv,Star pt,int trackRadius,Color color)
    {
    this.name=name;
    this.radius=r;
    this.selfRollVelocity=sv;
    this.publicRollTrack=pt;
    this.publicRollTrackRadius=trackRadius;
    this.publicRollVelocity=pv;
    this.color=color;
    this.dir=new Point();
    this.curPosition=new Point();
    }
    @Override
    public void draw(Graphics g)
    {
    Color c=g.getColor();
    g.setColor(color);
    g.fillOval(curPosition.x-radius/2, curPosition.y-radius/2, radius, radius);
    g.setColor(Color.BLACK);
    g.fillOval(dir.x+curPosition.x, dir.y+curPosition.y, 5,5);
    g.setColor(c);
    } @Override
    public Point getCurPosition()
    {
    return curPosition;
    } @Override
    public void publicRoll(long timeElapse)
    {
    this.publicRollTrackAngle+=1.0*timeElapse*publicRollVelocity/10000;
    Point oPoint=publicRollTrack.getCurPosition();
    curPosition.setLocation(Math.cos(publicRollTrackAngle)*publicRollTrackRadius+oPoint.x,Math.sin(publicRollTrackAngle)*publicRollTrackRadius+oPoint.y);
    }
    @Override
    public void selfRoll(long timeElapse)
    {
    this.selfRollTrackAngle+=1.0*timeElapse*selfRollVelocity/1000;
    dir.setLocation(Math.cos(selfRollTrackAngle)*radius*0.35,Math.sin(selfRollTrackAngle)*radius*0.35);
    }
    }
    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Point;public class FixedStar implements Star
    {
    private Point curPosition;
    private int selfRollVelocity;
    private int radius;
    private Point dir;
    private Color color;
    private String name;
    private double selfRollTrackAngle;

    public FixedStar(String name,Point cp,int r,int sv,Color color)
    {
    this.name=name;
    this.curPosition=cp;
    this.radius=r;
    this.selfRollVelocity=sv;
    this.color=color;
    this.dir=new Point();
    }
    @Override
    public void draw(Graphics g)
    {
    Color c=g.getColor();
    g.setColor(color);
    g.fillOval(curPosition.x-radius/2, curPosition.y-radius/2, radius, radius);
    g.setColor(Color.BLACK);
    g.fillOval(dir.x+curPosition.x, dir.y+curPosition.y, 10,10);
    g.setColor(c);
    } @Override
    public Point getCurPosition()
    {
    return curPosition;
    } @Override
    public void publicRoll(long timeElapse)
    {
    }
    @Override
    public void selfRoll(long timeElapse)
    {
    this.selfRollTrackAngle+=1.0*timeElapse*selfRollVelocity/1000;
    dir.setLocation(Math.cos(selfRollTrackAngle)*radius*0.35,Math.sin(selfRollTrackAngle)*radius*0.35);
    }
    }
    import java.awt.*;
    import java.awt.image.*;
    import java.util.*;
    import javax.swing.JFrame;
    import javax.swing.JPanel;public class God extends JFrame
    {
    private JPanel panel;
    private ArrayList<Star> stars=new ArrayList<Star>() ; public God()
    {
    super("Sun-Earth-Moon System!");
    // 创建面板
    panel = new JPanel(true);
    panel.setBounds(0, 0, 500, 500);
    panel.setBackground(Color.WHITE);
    // 创建容器
    Container c = this.getContentPane();
    c.setLayout(null);
    c.add(panel); this.setBounds(0, 0, 500, 500);
    this.setResizable(false);
    this.setVisible(true);
    this.setDefaultCloseOperation(EXIT_ON_CLOSE); StarFactory factory = new StarFactory();
    Star sun = factory.createFixedStar("sun", new Point(250, 250), 100, 1,Color.RED);
    Star earth = factory.createPlanet("earth", 50, 5, 2, sun, 150,Color.BLUE);
    Star moon = factory.createPlanet("moon", 20, 3, 5, earth, 50,Color.YELLOW);
    stars.add(sun);
    stars.add(earth);
    stars.add(moon);

    run();
    } private void show(long timeElapse)
    {
    Image bufferImage=new BufferedImage(500,500,BufferedImage.TYPE_4BYTE_ABGR);
    Graphics graphics=bufferImage.getGraphics();
    for(int i=0;i<stars.size();++i)
    {
    stars.get(i).selfRoll(timeElapse);
    stars.get(i).publicRoll(timeElapse);
    stars.get(i).draw(graphics);
    }
    panel.getGraphics().drawImage(bufferImage,0,0,Color.WHITE,null);
    } public void run()
    {
    show(0);
    java.util.Date lastTimeDate=new java.util.Date();
    while(true)
    {   
    java.util.Date curTimeDate=new java.util.Date();
    long timeElapse=curTimeDate.getTime()- lastTimeDate.getTime();
    if(timeElapse>40)
    {
    lastTimeDate=curTimeDate;
    show(timeElapse);
    }
    try
    {
    Thread.sleep(1);
    }
    catch (InterruptedException e)
    {
    e.printStackTrace();
    }
    }
    } public static void main(String[] args)
    {
    new God();
    }
    }