我目前正在修改一个有9种不同构造函数的类.总的来说,我认为这个类的设计非常糟糕...所以我想知道如果一个类有这么多构造函数的设计是不好的.
出现了一个问题,因为我最近在这个类中添加了两个构造函数,试图重构和重新设计一个类(下面代码中的SomeManager),这样它就是单元可测试的,并且不依赖于它的每个方法都是静态的.但是,因为其他构造函数在类的开头以下方便地隐藏了大约一百行,所以当我添加构造函数时,我没有发现它们.
现在发生的是调用这些其他构造函数的代码依赖于已经实例化的SomeManager类,因为它曾经是静态的......结果是一个空引用异常.
所以我的问题是如何解决这个问题?通过尝试减少构造函数的数量?通过使所有现有构造函数采用ISomeManager参数?
当然一个班级不需要9个构造函数!...哦,最重要的是这个文件中有6000行代码!
这是我正在讨论的构造函数的审查表示:
public MyManager()
: this(new SomeManager()){} //this one I added
public MyManager(ISomeManager someManager) //this one I added
{
this.someManager = someManager;
}
public MyManager(int id)
: this(GetSomeClass(id)) {}
public MyManager(SomeClass someClass)
: this(someClass, DateTime.Now){}
public MyManager(SomeClass someClass, DateTime someDate)
{
if (someClass != null)
myHelper = new MyHelper(someOtherClass, someDate, "some param");
}
public MyManager(SomeOtherClass someOtherClass)
: this(someOtherClass, DateTime.Now){}
public MyManager(SomeOtherClass someOtherClass, DateTime someDate)
{
myHelper = new MyHelper(someOtherClass, someDate, "some param");
}
public MyManager(YetAnotherClass yetAnotherClass) …Run Code Online (Sandbox Code Playgroud) 我试图围绕面向对象的编程.
我的理解是我们有对象,所以我们可以设计我们的程序来镜像现实生活中的对象.
我们来看一个类层次结构:
class Fruit {
void Eat() {
}
}
class Apple extends Fruit {
}
Run Code Online (Sandbox Code Playgroud)
显然,如果Eat()是虚拟的,你可以多态地使用Fruit .但这有意义吗?水果不能自己吃!
水果对象应该传递给具有Eat()功能的人体物体吗?
我试图弄清楚正确的思考方式.一般来说,编程对象应该如何接近现实生活中的对象?
是否可以在静态方法中返回一个类?我会解释...
我有:
public class A { public static void blah(){} }
public class B { }
Run Code Online (Sandbox Code Playgroud)
我想在B女巫回归中创建一个静态方法A.所以你可以这样做:
A.blah();
Run Code Online (Sandbox Code Playgroud)
和
B.getA().blah();
Run Code Online (Sandbox Code Playgroud)
这样,无需创建实例A.只需使用它静态方法.
这可能吗?
有些人知道.NET在内存中保存值类型(主要是在堆栈中,但在某些情况下可能在堆中等)......
我的问题是 - 结构的代码在哪里?
如果我在结构中说16字节的数据字段并且在其中有一个大量的计算方法 - 我假设16个字节将被复制到堆栈中,方法代码存储在其他地方并且为结构的所有实例共享.
这些假设是否正确?
请看下面设计类聚合的两个简化示例.
解决方案1
头
// need include, forward declaration is not enough
#include "door.h"
class CGarage
{
public:
CGarage(const std::string &val);
private:
CDoor m_door;
};
Run Code Online (Sandbox Code Playgroud)
资源
#include "garage.h"
CGarage::CGarage(const std::string &val)
:m_door(val)
{
}
Run Code Online (Sandbox Code Playgroud)
解决方案2
头
#include "smart_ptr.hpp"
// forward declaration
class CDoor;
class CGarage
{
public:
CGarage(const std::string &val);
private:
scoped_ptr<CDoor> m_door;
};
Run Code Online (Sandbox Code Playgroud)
资源
#include "garage.h"
#include "door.h"
CGarage::CGarage(const std::string &val)
:m_door(new CDoor(val))
{
}
Run Code Online (Sandbox Code Playgroud)
有关创建CDoor成员的问题
您在示例设计中看到了哪些优点/缺点(CDoor与自动分配的动态分配)?
这就是我想出的:
解决方案1:
+没有内存处理或生命周期的问题
+在运行时不需要昂贵的内存分配
- 在头文件中需要额外的包含(编译速度更慢?,更接近CDoor) - >头文件中的许多包含被认为是坏的...
解决方案2:
+标头中的CDoor松散耦合(仅需要前向声明)
- 内存需要由程序员处理
您通常喜欢哪种设计?
我有一个应用程序,它本质上是第三方API的包装器.该应用程序不使用数据库,只存储单个cookie,这是API所需的会话ID.
API是一个允许用户使用的购物系统
-login/register/edit profile/logout
- 买的商品
-做捐献
-成为会员
API有50个左右的方法,我的应用程序需要连接到这些方法.示例API调用是addItemToBasket(),addDonation(),GetUserDetails()等.
我试图弄清楚我的应用程序中应该是什么类.这是我到目前为止:
类
1)APIManager()类 包含与第三方API中公开的方法一对一匹配的方法,并提供与远程API服务器建立连接的机制.因此用户将通过登录
APIManager->loginUser($sessionKey, $uid, $pwd);
Run Code Online (Sandbox Code Playgroud)
并且远程API会将用户设置为已登录.如果需要,我的应用程序可以通过调用API来检查任何会话密钥的登录状态:
APIManager->isLoggedIn($sessionKey);
Run Code Online (Sandbox Code Playgroud)
2)User()类 这包含在处理API调用(如Register或Login)之前包含所需业务逻辑的方法.一个示例方法是:
function login($_POST) {
//perform sanity checks, apply business rules etc.
//if certain conditions are met, we may pass in a promo code, $pc
APIManager->loginUser($sessionkey, $_POST['uid'], $_POST['pwd'], $pc);
}
Run Code Online (Sandbox Code Playgroud)
我意识到我可能只是从登录页面调用APIManager,而不是拥有User类本身,但我觉得因为在我们实际调用API的loginUser()方法之前需要运行一些业务逻辑,所以感觉有权在User类中处理.我很想知道人们对此的看法.
3)篮子()类
篮子是在第三方API中管理的,所以我的应用程序的作用是进行适当的API调用以将新项目添加到购物篮,删除项目,查看购物篮等.我的应用程序对篮子一无所知,直到从中检索数据API,也不能通过API进行任何更改.同样,将这种相关逻辑分组到Basket类中是合适的.前端网页可能会调用以下内容:
Basket->addItem(23);
Run Code Online (Sandbox Code Playgroud)
而这个Basket类中的addItem()方法看起来像:
addItem($itemID) {
//perform checks, apply business rules e.g. if user is eligible for discount
APIManager->addToCart($itemID, $discount);
}
Run Code Online (Sandbox Code Playgroud)
其中addToCart()是我们调用来处理项目的第三方API方法.
4)捐赠()类
这允许用户进行捐赠.捐赠出现在篮子里,可以从篮子里取出.我想到只是在Basket类中添加一个addDonate()方法而不用担心有Donation对象,但是......(见下文)
5)会员资格()类
...会员资格实际上是一种捐赠!该API将捐赠进入某个帐户作为1年会员资格,而不是简单的捐赠.我们无法更改第三方API的逻辑/行为. …
我一直在开发一些手机游戏,其中那些游戏从服务器数据库中获取数据.
我习惯将"type"值存储为整数标识符,并在客户端中使用枚举来标识来自服务器的数据.
举个例子:在数据库表上:
怪物表:MonsterId(int),名称(字符串),MonsterType(int)
在客户端代码上:
typedef enum {
MonsterTypeGround = 1,
MonsterTypeAquatic = 2,
MonsterTypeAmphibious = 3,
MonsterTypeAerial = 4
}MonsterType;
Run Code Online (Sandbox Code Playgroud)
请注意,上面的代码是Objective-C,我可以在其中指定整数值.但我也在使用C#和C++.
但是,我们的数据库人说,枚举是一个编译技巧,没有枚举数据类型.他认为整数类型标识符使得人们(其他开发人员)很难理解值的含义,并且他们不可能在不查看客户端代码的情况下知道等价物并且枚举不好因为你需要确保枚举与服务器端ID同步,并且最好使用字符串.
我的问题是:在这个问题上是否有客观正确的答案?
除了在客户端代码上使用枚举之外还有其他选择,但仍然会使用整数作为服务器数据库吗?
假设我有一个带有滑块的主窗口和一个窗口内的窗口小部件,其方法称为setValue(int).每次滑块的值发生变化时,我都想调用此方法.
以下两种实现方式之间是否存在实际差异:
void MainWindow::on_slider_valueChanged(int value)
{
ui->widget->setValue(value);
}
Run Code Online (Sandbox Code Playgroud)
// somewhere in constructor
connect(ui->slider, SIGNAL(valueChanged(int)), ui->widget, SLOT(setValue(int)));
Run Code Online (Sandbox Code Playgroud)
对我来说,第一种方法看起来更好,因为它可能避免与信号和插槽机制相关的一些开销,并且,如果需要它,允许我value在发送之前处理widget它.
是否存在第二种解决方案更好的情况?
可能相关:
为什么PHP属性不允许函数?
请原谅我,如果以前曾经问过这个问题,但为什么你不能得到以下内容:
class foo {
require_once 'defines.php';
private $_server = DB_SERVER;
private $_username = DB_USERNAME;
private $_password = DB_PASSWORD;
private $_database = DB_NAME;
public $debug = false;
public $_conn;
function __construct() {
$connection = @mysqli_connect($this->_server, $this->_username, $this->_password, $this->_database);
}
...
}
Run Code Online (Sandbox Code Playgroud)
干杯,
编辑:寻找为什么这种行为存在以及为什么不可能.如何结束投票?
EDIT2:还想重新打开这个
这是一个面试问题.
使用面向对象原则设计一个tic tac toe.采访者说他对逻辑不感兴趣,他只想要设计.我给出了如下设计,但我并不完全满意.如果有任何建议/改进,请告诉我.
面试官对两件事非常讲究
我的方法:
类的粗略草图.
interface Player {
Player takeTurn();
void markNextBox();
}
Run Code Online (Sandbox Code Playgroud)
.
public class TicTacToeGameEngine implements GameRule{
@Override
public Boolean isWinner(Game game) {
// Check winner logic
return false;
}
@Override
public Square locateSquareToMark(Game game) {
List<Square> squares= game.getBoard().getFilledSquares();
//go through the list of squares and figure out a square to mark
return square;
}
}
Run Code Online (Sandbox Code Playgroud)
.
public class Computer implements Player { …Run Code Online (Sandbox Code Playgroud) class-design ×10
oop ×3
c++ ×2
java ×2
php ×2
c# ×1
constructor ×1
enums ×1
qt ×1
return-value ×1
static ×1
struct ×1
value-type ×1